Codeka 给出的示例是正确的,我建议在表示层调用该方法时使用此代码编写代码。但是,处理 DataContext 类有点棘手,所以我想对此添加一些内容。
LINQ to SQL 生成的域对象(在您的情况下为 TB_Countries 类)通常包含对 DataContext 类的引用。延迟加载需要此内部引用。当您访问引用对象的实例列表(例如:TB_Country.States)时,LINQ to SQL 将为您查询数据库。延迟加载的列也会发生这种情况。
当您处理 DataContext 时,您会阻止它再次被使用。因此,当您像在示例中所做的那样返回一组对象时,不可能在 TB_Country 实例上调用 States 属性,因为它会抛出 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 here 上写了更多关于他的文章。在这种情况下,您的方法基本上如下所示:
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; }
}
正如您将阅读的 here,您可以做一些聪明的事情来减少使用 DTO 的痛苦。
我希望这会有所帮助。