Why can I list a DbLinq request after calling Dispose () in a DataContext?

Refresh . The answer seems to be that DbLinq does not implement Dispose() properly. D'o!


Below are just a few misleading. Bottom line: DbLinq is not yet equivalent to LinqToSql, as I expected when I initially asked this question. Use it with caution!

I am using a repository template with DbLinq. My storage objects implement IDisposable , and the Dispose() method does only one thing - it calls Dispose() on the DataContext . Whenever I use the repository, I move it to the using block, for example:

 public IEnumerable<Person> SelectPersons() { using (var repository = _repositorySource.GetPersonRepository()) { return repository.GetAll(); // returns DataContext.Person as an IQueryable<Person> } } 

This method returns an IEnumerable<Person> , so if my understanding is correct, the database query is not executed until the Enumerable<Person> is passed (for example, by converting it to a list or array or by using it in foreach ), as in this example:

 var persons = gateway.SelectPersons(); // Dispose() is fired here var personViewModels = ( from b in persons select new PersonViewModel { Id = b.Id, Name = b.Name, Age = b.Age, OrdersCount = b.Order.Count() }).ToList(); // executes queries 

In this example, Dispose() is called right after setting persons , which is an IEnumerable<Person> , and that is the only time it is called.

So, three questions:

  • How it works? How does the remote DataContext still query the database for the results after the DataContext been deleted?
  • What does Dispose() actually do?
  • I heard that there is no need (for example, see this question ) to get rid of the DataContext , but I got the impression that this is not a bad idea. Is there a reason not to get rid of the DbLinq DataContext ?
+7
c #
source share
3 answers

1 How does it work? How does the remote DataContext still query the database for results after placing the DataContext?

It does not work . There you are not showing us something. I assume that either your repository class does not manage the DataContext properly / at the right time, or that you randomly write ToList() at the end of each request, which completely negates the conversion of the request and you usually get deferred execution.

Try using the following code in a test application, I guarantee that it will throw an ObjectDisposedException :

 // Bad code; do not use, will throw exception. IEnumerable<Person> people; using (var context = new TestDataContext()) { people = context.Person; } foreach (Person p in people) { Console.WriteLine(p.ID); } 

This is the easiest reproducible event possible, and it will always throw. On the other hand, if you write people = context.Person.ToList() instead, then the query results are already listed inside the using block that I put on, this is what happens in your case.

2 What does Dispose () actually do?

Among other things, it sets a flag indicating that a DataContext is located, which is checked at each subsequent request, and raises a DataContext to throw an ObjectDisposedException with the message Object name: 'DataContext accessed after Dispose.'.

It also closes the connection if the DataContext opened it and left it open.

3 I heard that there is no need (for example, to see this question) to get rid of the DataContext, but I got the impression that this is not a bad idea. Is there a reason not to get rid of the DataContext LinqToSql?

Dispose DataContext required , since it is necessary to Dispose each other IDisposable . You can potentially leak connections if you do not delete the DataContext . You can also skip memory if any of the objects obtained from the DataContext are kept alive, because the context supports an internal cache identifier for the unit of work template it implements. But even if it is not, you don’t have to worry about what the Dispose method does internally. Suppose he is doing something important.

IDisposable is a contract that states: "cleaning may not be automatic, you need to spare me when you are done." You have no guarantee that the object has its own finalizer, which will clear after you if you forget Dispose . Implementations are subject to change, so you should not rely on the observed behavior, and not on explicit specifications.

The worst thing that can happen if you choose IDisposable with an empty Dispose method is that you spend several processor cycles. The worst thing that can happen if you do not remove IDisposable with a non-trivial implementation is a resource leak. The choice is obvious; if you see IDisposable , do not forget to delete it.

+3
source share

"people" is an IEnumerable collection, a DataContext (repository) is required only to call .GetNew.

The / select / etc keywords are syntactic sugar for extension methods added to the System.Linq namespace. These extension methods add the IEnumerable functionality that you use in your request, not the DataContext. In fact, you can do all this without using LINQ2SQL at all, by creating IEnumerable programmatically for demonstration.

If you try to make any subsequent call to the repository (DataContext) using these objects, this will happen when you receive an error message.

The IEnumerable collection will contain ALL records from your repository, so you do not need the DataContext to execute the request.

Extension Methods: http://msdn.microsoft.com/en-us/library/bb383977.aspx

LINQ extension methods: http://msdn.microsoft.com/en-us/library/system.linq.enumerable_members.aspx

0
source share

Inside the API, you are likely to see a method using api, like this one:

http://msdn.microsoft.com/en-us/library/y6wy5a0f(v=VS.100).aspx

When the command is executed, the associated Connection object is closed when the associated DataReader object is closed.

0
source share

All Articles