Linq DataContext и Dispose

7 окт. 2011 г. | | |

Как известно, любой DataContext объект является IDisposable. При использовании конструкции вида
using (CDataContext db = new CDataContext(ConnectionPool.Connection)) {...}
метод  Dispose() вызывается автоматически, и все занимаемые ресурсы освобождаются.
Насколько критично вызывать метод Dispose() вручную для такого кода?
CDataContext db = new CDataContext(ConnectionPool.Connection);
 return (from tbl in db._addresses
        where tbl.IsCustomer.Equals(true)
        select tbl).ToList();

Перефразируя вопрос: что плохого случится, если не вызвать  Dispose()? Ведь GC всё равно вызовет этот метод, разве что не сразу. DataContext не держит соединение c БД открытым (только, если не открывать его явным способом вроде DataContext.Connection.Open() ) т.е. никаких тяжеловесных ресурсов не занимает, и ничего плохого не происходит. Т.е. совсем не обязательно вручную вызывать Dispose().
Но. Если вы напишите такой код
using(CDataContext db = new CDataContext(ConnectionPool.Connection))
{
    return (from tbl in db._addresses
            where tbl.IsCustomer.Equals(true)
            select tbl);

}
произойдёт исключение "Cannot access a disposed object. Object name: 'DataContext accessed after Dispose.", потому что дерево запроса (возвращаемый тип  IQueryable<_address>) попытается выполнится после того, как DataContext будет уничтожен. Произойдёт это потому, что запрос выполнится тогда, когда будет впервые вызвано перечисление элементов (метод ToList<T>(), например). Если же написать такой код
CDataContext db = new CDataContext(ConnectionPool.Connection)
 return (from tbl in db._addresses
        where tbl.IsCustomer.Equals(true)
        select tbl);

то нужно понимать, что DataContext откроет соединение к базе, извлечет элементы и будет уничтожен только в том месте кода, где произойдет IQueryable<_address>.ToIEnumerable<_address>()

0 коммент.:

Отправить комментарий