Должен ли я доверять LinqDataSource для правильной очистки?
Взяв мой первый удар за использование метода OnSelecting LinqDataSource, чтобы я мог указать более сложный запрос, я написал это:
protected void CategoriesDataSource_OnSelecting(object sender, LinqDataSourceSelectEventArgs e)
{
using (DataLayerDataContext db = new DataLayerDataContext())
{
e.Result = (from feed in db.Feeds
where feed.FeedName.StartsWith("Google")
select feed.MainCategory).Distinct();
}
}
Проблема, конечно, заключается в том, что предложение using будет утилизировать DataLayerDataContext. "Решение" состоит в том, чтобы написать его без него, но я боюсь, что контекст не будет своевременно удален, что он оставит открытыми несколько соединений, пока не будет запущена сборка мусора, и так далее.
Я не эксперт в этой области, поэтому есть какие-либо комментарии по поводу того, является ли это реальной проблемой, или я беспокоюсь за ничто?
1 ответ
Ах, еще один человек сгорел от неудачных побочных эффектов отложенной загрузки...
protected void CategoriesDataSource_OnSelecting(object sender, LinqDataSourceSelectEventArgs e)
{
using (DataLayerDataContext db = new DataLayerDataContext())
{
e.Result = (from feed in db.Feeds
where feed.FeedName.StartsWith("Google")
select feed.MainCategory).Distinct().ToList();
// ^^^^^^^^^
}
}
Это заставит DataLayerDataContext
немедленно выполнить запрос и создать список в памяти, который не зависит от контекста или соединения. Таким образом, вы сразу получите свои результаты и можете распоряжаться контекстом в любое время.
Единственная проблема (согласно комментарию Стивена) - это лениво загруженные свойства навигации; даже если вы заставите запрос выполнить оценку, если вы попытаетесь запросить какие-либо свойства, которые являются ссылками на другие объекты LINQ (или списки объектов LINQ), они не смогут загружаться, если вы не укажете, какие свойства требуются немедленно в DataLoadOptions
из DataContext
, Смотрите ниже пример:
protected void CategoriesDataSource_OnSelecting(object sender, LinqDataSourceSelectEventArgs e)
{
using (DataLayerDataContext db = new DataLayerDataContext())
{
DataLoadOptions loadOptions = new DataLoadOptions();
loadOptions.LoadWith<Category>(c => c.SomeReference);
loadOptions.LoadWith<Category>(c => c.SomeOtherReferences);
db.LoadOptions = loadOptions;
e.Result = (from feed in db.Feeds
where feed.FeedName.StartsWith("Google")
select feed.MainCategory).Distinct().ToList();
}
}
После того, как вы вручную зададите эти ассоциации, LINQ to SQL будет охотно загружать их в память при выполнении запроса, а не оставлять их для отложенной загрузки (что приведет к исключению, когда свойства используются после DataContext
расположен.)