我有一个复杂的查询,我在我的代码中多次使用。我用它来获取所有项目或只有一个项目:
from item in _db.Tests ... select getItem(item)
from item in _db.Tests ... where item.Id == id select getItem(item)
如果我真的要使用它,我不想重复使用公共部分,只调用“getItem”。
我尝试创建一个类似的函数:
from item in _db.Tests ...
但编译器抱怨,因为我没有选择。
我还可以创建一个:
private IQueryable<Test> getTests()
{
return from item in _db.Tests ... select item;
}
然后像这样调用它:
from t in getTests() select getItem(t)
但那可能不会利用LINQ能够实现的优化......对吗?
你能帮帮我吗?
修改
我意识到我的问题更复杂:点(...)实际上是连接,而getItem函数使用来自连接的信息并进行一些计算。
另外,我想有一个函数来获取所有项目和一个不同的项目以获取特定项目(我想隐藏查询逻辑与程序的其余部分)。
我在考虑这样做:
private IQueryable<Tuple<Table1, Table2, Table3, Table4>> queryItems()
{
return from t1 in _db.Table1s
join t2 in _db.Table2s on t1.T2ID equals t2.ID into outerT2 from t2 in outerT2.DefaultIfEmpty()
join t3 in _db.Table3s on t1.T3ID equals t3.ID into outerT3 from t3 in outerT3.DefaultIfEmpty()
join t4 in _db.Table4s on t1.T4ID equals t4.ID into outerT4 from t4 in outerT4.DefaultIfEmpty()
select new Tuple<Table1, Table2, Table3, Table4>(t1, t2, t3, t4);
}
public IEnumerable<Item> GetItems()
{
return from i in queryItems()
select getItem(i.Item1, i.Item2, i.Item3, i.Item4);
}
public Item GetItem(int id)
{
return from i in queryItems()
where i.Item1.ID equals id
select getItem(i.Item1, i.Item2, i.Item3, i.Item4);
}
我不想把getItem放在queryItems中因为它做了一些计算,而在GetItem(int id)的情况下,它会为每个元素运行它(对吗?)。
这是一个很好的工作方式吗?有更漂亮的方式吗?一种更有效的方式?
答案 0 :(得分:6)
您可以使用相同的查询,只需根据需要添加条件:
var items = from item in _db.Tests ... select getItem(item);
// Restrict as necessary
if (fetchSingle)
items = items.Where(item => item.Id == id);
将过滤器(Where
)拆分为单独的调用没有任何缺点,因为当您实际使用由于LINQ&#39;而导致的结果IQueryable<T>
时,它会向服务器发送相同的查询。推迟执行。
答案 1 :(得分:3)
但那可能不会利用LINQ能够实现的优化......对吗?
不正确的。直到您实际尝试迭代查询提供程序尝试将IQueryable
转换为实际数据库查询并执行它的查询。当你有类似的东西时:
var query = db.SomeTable;
你没有取整张桌子;你已经提取了没有。如果你那么:
var query2 = query.Where(item => item.SomeProperty == "someValue");
然后查询提供程序将该筛选器应用于它发送到数据库的查询。
了解正在发生的事情的最简单/最好的方法是查看数据库上下文的Log
值。它将准确指示您执行查询的时间以及查询的内容。然后,您可以确定您正在执行的应该是您应该的查询。