2

我一直在阅读 Ienumerables 不会立即运行。所以我试图找到查询列表的最佳方法。

下面是我的 getAll 方法。其次是我的过滤方法。其次是首选的过滤方法(可读性)。

我的问题是,第三种方法和直接查询一样吗?换句话说,它会,还是不会从数据库加载所有 myObjects 然后过滤?或从数据库获取时进行过滤。

   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);
    }

或者,如果您有更好的建议,我会全力以赴。

4

2 回答 2

3

它会,还是不会从数据库中加载所有 myObjects 然后过滤?

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

任何过滤,即您的Where子句,都将在数据库端完成。

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

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);
}

更新

正如您刚刚指出的那样,您使用WebMatrix.Database的上述任何方法都不适用,因为这里没有发生延迟执行。Query方法立即执行并返回结果集,IEnumerable<T>因此任何过滤应用的后记都将在内存中完成。所以就效率而言,第一种过滤方法会更好,因为它在数据库端完成所有工作。

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

于 2013-01-10T11:37:40.523 回答
2

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

于 2013-01-10T11:31:35.140 回答