Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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# Linq和IEnumerable惰性查询。效率损失?_C#_Performance_Linq_Ienumerable - Fatal编程技术网

C# Linq和IEnumerable惰性查询。效率损失?

C# Linq和IEnumerable惰性查询。效率损失?,c#,performance,linq,ienumerable,C#,Performance,Linq,Ienumerable,我一直在读到,Ienumerables不会马上逃跑。因此,我试图找到查询列表的最佳方法 下面是我的getAll方法。然后是我的过滤方法。然后是首选的筛选方法(可读性) 我的问题是,第三种方法是否与直接查询相同?换句话说,它是否会从数据库加载所有MyObject,然后进行过滤?或从数据库获取时进行过滤。 public static IEnumerable<myObject> getAll() { using (var db = Database.OpenC

我一直在读到,Ienumerables不会马上逃跑。因此,我试图找到查询列表的最佳方法

下面是我的getAll方法。然后是我的过滤方法。然后是首选的筛选方法(可读性)

我的问题是,第三种方法是否与直接查询相同?换句话说,它是否会从数据库加载所有MyObject,然后进行过滤?或从数据库获取时进行过滤。

   public static IEnumerable<myObject> getAll()
    {
        using (var db = Database.OpenConnectionString(blahblah))
        {
            var queryResults = db.Query("SELECT * FROM vu_myObjects");

            return queryResults .Select(x => new myObject(x.myObjectName, x.myObjectF));
        }
    }

    public static IEnumerable<myObject> getAllForFilter(String filter)
    {
        using (var db = Database.OpenConnectionString(blahblah))
        {
            var queryResults  = db.Query("SELECT * FROM vu_myObjects WHERE ObjectF = @0", filter);

            return queryResults.Select(x => new myObject(x.myObjectName, x.ObjectF));
        }
    }

   public static IEnumerable<myObject> getAllForFilter(String filter)
    { // Not checked syntax.
        return getAll().Where(x => x.ObjectF = filter);
    }
公共静态IEnumerable getAll()
{
使用(var db=Database.OpenConnectionString(blahblah))
{
var queryResults=db.Query(“从vu_myObjects中选择*);
返回queryResults.Select(x=>newmyobject(x.myObjectName,x.myObjectF));
}
}
公共静态IEnumerable getAllForFilter(字符串筛选器)
{
使用(var db=Database.OpenConnectionString(blahblah))
{
var queryResults=db.Query(“从vu_myObjects中选择*其中ObjectF=@0”,过滤器);
返回queryResults.Select(x=>newmyobject(x.myObjectName,x.ObjectF));
}
}
公共静态IEnumerable getAllForFilter(字符串筛选器)
{//未检查语法。
返回getAll(),其中(x=>x.ObjectF=filter);
}

或者,如果你有更好的建议,我洗耳恭听。

它们基本上是一样的。在您真正询问从getAlLForFilter调用返回的IEnumerable之前,它将是一个延迟计算的查询。如果对其调用.ToList()或访问其内容,则此时它将调用数据库。如果在第三次调用时设置断点,您将看到它不会包含查询结果,直到您告诉调试器对查询进行求值

它会,还是会从数据库加载所有MyObject,然后进行过滤


它不会,因为您还没有实际查询数据库
IQueryable
已延迟执行,因此为了实际返回结果集,您需要执行查询。这可以通过两种方式完成,例如调用
ToList
或迭代列表

任何过滤,即您的
Where
子句,都将在DB端进行

实际上,您目前拥有的代码甚至无法工作—它会抛出一个
ObjectDisposedException
,因为您在处理数据上下文后试图对延迟查询应用过滤器。要使代码正常工作,您需要将
where
子句作为参数传递给
getAll
方法,例如

public static IEnumerable<myObject> getAll(Expression<Func<myObject,bool>> where)
{
    using (var db = Database.OpenConnectionString(blahblah))
    {
        var queryResults = db.Query("SELECT * FROM vu_myObjects");
        if (where != null)
        {
            queryResults.Where(where);
        }
        return queryResults .Select(x => new myObject(x.myObjectName, x.myObjectF));
    }
}

public static IEnumerable<myObject> getAllForFilter(String filter)
{ // Not checked syntax.
    return getAll(x => x.ObjectF = filter);
}
公共静态IEnumerable getAll(表达式,其中)
{
使用(var db=Database.OpenConnectionString(blahblah))
{
var queryResults=db.Query(“从vu_myObjects中选择*);
if(其中!=null)
{
查询结果。何处(何处);
}
返回queryResults.Select(x=>newmyobject(x.myObjectName,x.myObjectF));
}
}
公共静态IEnumerable getAllForFilter(字符串筛选器)
{//未检查语法。
返回getAll(x=>x.ObjectF=filter);
}
更新

正如您刚才指出的,您使用的是
WebMatrix.Database
,由于这里没有延迟执行,因此上述任何一项都不适用。该方法立即执行,并返回一个结果集
IEnumerable
,因此任何应用于后置词的过滤都将在内存中完成。因此,在效率方面,第一种过滤方法会更好,因为它在DB端处理所有事情


通过将
Where
子句转换为实际字符串并将其附加到查询中,您可以同时获得可读性和效率。

IQueryable
延迟了执行…哦,其他人不这么认为:(我的错-我在考虑你使用ORM-正如@James所说的,如果你使用IQueryable,那么你会延迟执行,我可能应该提到使用WebMatrix.Data;的
是我使用的
数据库
对象。是IQueryable吗?那么我认为它延迟执行是真的吗?谢谢你的信息和建议。)这些想法帮助我产生了一些可读的、高效的方法。谢谢。在评测时,DB被点击在
DB.Query()上
那么我应该使用什么样的
数据库
类来保持API的易用性呢?@Mcloving我不确定你在这里要问什么?@Mcloving似乎很好,我想一个小的改进是在方法签名中提供
where
参数
的默认值
null
,这样你就可以用ut必须自己指定空值(您需要至少使用C#4.0才能做到这一点)。否则,您可以只添加一个重载方法。此外,我建议在该方法中执行一些参数检查,并在必要时抛出适当的异常,即如果您有where子句,则参数列表不应为null或空等。