Пример, данный Codeka, верен, и я бы посоветовал написать ваш код с этим, когда метод вызывается уровнем представления. Однако избавиться от DataContext
классов немного сложно, поэтому я хотел бы добавить кое-что по этому поводу.
Объекты домена, сгенерированные LINQ to SQL (в вашем случае класс TB_Countries
) часто содержат ссылку на класс DataContext
. Эта внутренняя ссылка необходима для отложенной загрузки. Когда вы получаете доступ, например, к списку объектов, на которые ссылаются (например, TB_Country.States
), LINQ to SQL запросит у вас базу данных. Это также произойдет с лениво загруженными столбцами.
Когда вы утилизируете DataContext
, вы предотвращаете его повторное использование. Поэтому, когда вы возвращаете набор объектов, как вы делали в вашем примере, невозможно вызвать свойство States
для экземпляра TB_Country
, потому что оно выдаст ObjectDisposedException
.
Это не значит, что вы не должны распоряжаться DataContext
, потому что я считаю, что вы должны. То, как вы должны решить эту проблему, немного зависит от выбранной вами архитектуры, но IMO у вас в основном есть два варианта:
Вариант 1. Поставьте DataContext
для метода GetCountriesQ
.
Обычно вы хотите сделать это, когда ваш метод является внутренним методом на бизнес-уровне и является частью более крупной (бизнес) транзакции. Когда вы предоставляете DataContext
извне, он создается за пределами области действия метода и не должен его утилизировать. Вы можете расположить его на более высоком уровне. В этой ситуации ваш метод в основном выглядит следующим образом:
public static IQueryable<TB_Country> GetCountriesQ(
Bn_Master_DataDataContext db)
{
return db.TB_Countries.OrderBy(o => o.CountryName);
}
Вариант 2. Не возвращать никакие доменные объекты из метода GetCountriesQ
.
Это решение полезно, когда метод является общедоступным на вашем бизнес-уровне и будет вызываться на уровне представления. Вы можете обернуть данные в специально созданный объект ( DTO ), который содержит только данные и не содержит скрытых ссылок на DataContext
. Таким образом, вы имеете полный контроль над связью с базой данных и можете распоряжаться DataContext
, как следует. Я написал больше о нем на SO здесь . В этой ситуации ваш метод в основном выглядит следующим образом:
public static CountryDTO[] GetCountriesQ()
{
using (var db = new Bn_Master_DataDataContext())
{
var countries;
from country in db.TB_Countries
orderby country.CountryName
select new CountryDTO()
{
Name = country.CountryName,
States = (
from state in country.States
order by state.Name
select state.Name).ToList();
};
return countries.ToArray();
}
}
public class CountryDTO
{
public string Name { get; set; }
public List<StateDTO> States { get; set; }
}
Как вы прочтете здесь есть некоторые умные вещи, которые вы можете сделать, чтобы сделать использование DTO менее болезненным.
Надеюсь, это поможет.