4

我创建了一个电话簿风格的应用程序;在我的电话簿对象上,我有一个_site用作过滤器的本地成员,因为大约有 1000 个电话号码,分布在我组织内的 12 个站点中。使用此方法一次只能检索一个站点。

这是我原来的方法。GUI 有几种重新排序数据的方法,因此我将其保留为 IQueryable,因为我想推迟 SQL 以允许在 SQL 服务器而不是客户端 PC 上完成过滤。

作品

public IQueryable<PhoneNumber> GetPhoneDirectory()
{
    PhoneBookDataContext db = new PhoneBookDataContext())
    return db.PhoneNumbers.Where(d => d.Site == _site);
}

但是,我也试图在using陈述方面保持“最佳实践”。

不工作

public IQueryable<PhoneNumber> GetPhoneDirectory()
{
    using (PhoneBookDataContext db = new PhoneBookDataContext())
    {
        return db.PhoneNumbers.Where(d => d.Site == _site);
    }
}

现在正如@justanotheruseryoumay 所指出的,这将导致异常,因为数据上下文在访问对象时已被释放。

我想我要问的是,当我不能使用“使用”语句并且不严格知道上下文何时完成时,如何确保我的数据上下文得到很好的处理。

4

3 回答 3

6

如果你想返回IQueryable,你可以让你的类包含GetPhoneDirectory一次性,创建PhoneBookDataContext一个字段,然后在你的 dispose 方法中处理它。

然后,您将有责任让调用者处理他的类实例。

例如

public class MyClass : IDisposable
{
    PhoneBookDataContext db;

    public MyClass()
    {
        db = new PhoneBookDataContext();
    }

    public IQueryable<PhoneNumber> GetPhoneDirectory()
    {
        return db.PhoneNumbers.Where(d => d.Site == _site);
    }

    public void Dispose()
    {
        if (db != null)
        {
            db.Dispose();
            db = null;
        }
    }
}

// Caller
using(var myClass = new MyClass())
{
    var queryable = myClass.GetPhoneDirectory();
    ...
}
于 2013-06-10T13:10:57.893 回答
0

是的; 这是一个糟糕的设计,因为IQueryable<PhoneNumber>只有当你调用一个导致它被评估的方法时,你才会被评估,比如ToList()或者当你用foreach.

在您的代码中,您正在返回IQueryable<PhoneNumber>尚未评估的a,并且在调用者有机会执行它之前,它的内部负责向您提供记录(db);已经处置。

就像一个建议:

public IEnumerable<PhoneNumber> GetPhoneDirectory()
{
    using (PhoneBookDataContext db = new PhoneBookDataContext())
    {
        return db.PhoneNumbers.Where(d => d.Site == _site).ToList();
    }
}

或者将 db 对象重新定位到设计中的其他位置(工作单元和存储库是很好的模式,可以查看恕我直言)。

于 2013-06-10T13:13:08.313 回答
0

查询的执行仍将被推迟,并且 PhoneBookDataContext 仍将被正确处理,因为 using 被编译器解释为 try/finally。当您实际执行查询时,它将导致运行时错误,因为 PhoneBookDataContext 不再存在。我建议对您的查询执行 .ToList() 并以这种方式返回。如果您想在退货后更改订单,那么您仍然可以随意对其进行 LINQ。

编辑: 您可以做的另一件事是在调用方法中使用 PhoneBookDataContext 创建使用并传入上下文。无论如何,上下文确实会在该方法中使用,只要您需要它就可以保留它,并坚持使用良好的使用格式。

于 2013-06-10T13:01:27.087 回答