Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从using块中返回IQueryable。需要更好的设计吗_C#_Linq_Linq To Sql_Using Statement - Fatal编程技术网

C# 从using块中返回IQueryable。需要更好的设计吗

C# 从using块中返回IQueryable。需要更好的设计吗,c#,linq,linq-to-sql,using-statement,C#,Linq,Linq To Sql,Using Statement,我已经创建了一个电话簿风格的应用程序;在我的电话簿对象上,我有一个本地成员\u站点,该站点用作过滤器,因为在我的组织内,大约有1000个电话号码,分为12个站点。使用此方法一次只能检索一个站点 这是我最初的方法。GUI有几种方法可以对数据进行重新排序,因此我将其保留为IQueryable,因为我希望延迟SQL以允许在SQL server上而不是在客户端PC上进行过滤 有效 public IQueryable<PhoneNumber> GetPhoneDirectory() {

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

这是我最初的方法。GUI有几种方法可以对数据进行重新排序,因此我将其保留为IQueryable,因为我希望延迟SQL以允许在SQL server上而不是在客户端PC上进行过滤

有效

public IQueryable<PhoneNumber> GetPhoneDirectory()
{
    PhoneBookDataContext db = new PhoneBookDataContext())
    return db.PhoneNumbers.Where(d => d.Site == _site);
}
正如@justanotheruseryoumay所指出的,这将导致异常,因为datacontext在访问对象时被释放


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

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

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

如果您想返回
IQueryable
您可以将包含
GetPhoneDirectory
的类设置为一次性,将
PhoneBookDataContext
设置为一个字段,并使用dispose方法对其进行处理

然后,您将把处理类实例的责任交给调用方

例如

公共类MyClass:IDisposable
{
PhoneBookDataContext数据库;
公共MyClass()
{
db=新的PhoneBookDataContext();
}
公共IQueryable GetPhoneDirectory()
{
返回db.PhoneNumbers.Where(d=>d.Site==\u Site);
}
公共空间处置()
{
如果(db!=null)
{
db.Dispose();
db=null;
}
}
}
//来电者
使用(var myClass=new myClass())
{
var queryable=myClass.GetPhoneDirectory();
...
}

是;这是一种糟糕的设计,因为只有在调用导致对其求值的方法(如
ToList()
或使用
foreach
对其进行迭代时,
IQueryable
才会求值

在您的代码中,您正在返回一个尚未计算的
IQueryable
,在调用方有机会执行它之前,它的内部负责向您生成记录(db);已被处置

正如一项建议:

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

或者将db对象重新定位到设计中的其他地方(工作单元和存储库是查看IMHO的好模式)。

尽管我不能确定,我相信问题在于
using
语句在对象超出范围之前无法
处理
对象,直到执行查询时才会发生这种情况。如果我在这里错了,有人会纠正我,但是在方法返回的第二次返回时,是否会标记任何局部变量进行处理?我认为上面的两个片段基本上是等价的。嗨,我编辑了我的问题,因为我没有明确提到第二个会引发异常。你应该让@justanotheruseryoumayknow,因为他们的答案似乎是正确的。他们删除了它,不知道如何联系他们。啊,我喜欢这个样子!我唯一的问题是,如果有人在创建“MyClass”和调用该方法之间向PhoneNumber插入一条记录,会发生什么?想必我总是接到SQL的新电话?
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();
    ...
}
public IEnumerable<PhoneNumber> GetPhoneDirectory()
{
    using (PhoneBookDataContext db = new PhoneBookDataContext())
    {
        return db.PhoneNumbers.Where(d => d.Site == _site).ToList();
    }
}