我一直在读,Ienumerables不会马上跑。所以我试图找到查询列表的最佳方法。
以下是我的getAll方法。接下来是我的过滤方法。接下来是一个首选的过滤方法(可读性)。
我的问题是,第三种方法是否与直接查询相同?换句话说,它会或者不会从数据库加载所有myObjects然后过滤?或者从DB获取时进行过滤。
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);
}
或者,如果你有更好的建议,我会全力以赴。
答案 0 :(得分:3)
它会不会从DB加载所有myObjects然后过滤?
不会,因为您还没有真正查询过数据库。因此,IQueryable<T>
已延迟执行,以便实际返回执行查询所需的结果集。这可以通过几种方式完成,例如调用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);
}
<强>更新强>
正如您刚刚指出的那样,您使用WebMatrix.Database
以上都不适用,因为这里没有发生延迟执行。 Query方法立即执行并返回IEnumerable<T>
的结果集,因此任何过滤后应用的过滤都将在内存中完成。因此,就效率而言,第一种过滤方法会更好,因为它在数据库方面做了所有事情。
您可以同时获得可读性和安全性。通过将Where
子句转换为实际字符串并将其附加到查询中来提高效率。
答案 1 :(得分:2)
他们基本上都是一样的。在你实际查询从getAlLForFilter调用返回的IEnumerable之前,它将是一个懒惰的评估查询。如果你在它上面调用.ToList()或访问内容,那么它将调用数据库。如果在第3次调用中设置断点,则在告诉调试器评估查询之前,您将看到它不会包含查询结果。