如何在使用后处理数据上下文

时间:2010-05-20 05:03:41

标签: asp.net datacontext iqueryable

我有一个从数据上下文返回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

2 个答案:

答案 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的痛苦减轻。

我希望这会有所帮助。