我有一个从数据上下文返回IQueryable的成员类
public static IQueryable<TB_Country> GetCountriesQ()
{
IQueryable<TB_Country> country;
Bn_Master_DataDataContext db = new Bn_Master_DataDataContext();
country = db.TB_Countries
.OrderBy(o => o.CountryName);
return country;
}
如您所见,我在使用后不会删除数据上下文。因为如果我删除它,调用此方法的代码不能使用IQueryable(可能是因为延迟执行?)。如何强制立即执行此方法?所以我可以处理数据上下文..
谢谢:D
答案 0 :(得分:3)
您可以将查询转换为列表,如下所示:
public static List<TB_Country> GetCountriesQ()
{
using(var db = new Bn_Master_DataDataContext())
{
return db.TB_Countries
.OrderBy(o => o.CountryName).ToList();
}
}
答案 1 :(得分:3)
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
方法返回任何域对象。
当方法在业务层中是公共方法并且将由表示层调用时,此解决方案很有用。您可以将数据包装在仅包含数据且不包含DataContext
隐藏引用的特制对象(DTO)中。这样您就可以完全控制与数据库的通信,并且可以根据需要处理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的痛苦减轻。
我希望这会有所帮助。