可扩展Linq查询
本文关键字:查询 Linq 可扩展 | 更新日期: 2023-09-27 18:17:00
我有一个复杂的查询,我在我的代码中使用了多次。我用它来获取所有项目或只获取一个项目:
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 ...
但是编译器报错,因为没有select
我也可以创建一个: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)的情况下,它会对每个元素运行它(对吗?)
这是做这项工作的好方法吗?有更漂亮的方法吗?一种更有效的方法?
您可以使用相同的查询,只需在需要时添加一个条件:
var items = from item in _db.Tests ... select getItem(item);
// Restrict as necessary
if (fetchSingle)
items = items.Where(item => item.Id == id);
将过滤器(Where
)分离成一个单独的调用将没有缺点,因为当您实际使用由于LINQ延迟执行而产生的IQueryable<T>
时,它将向服务器发送相同的查询。
但这可能不会利用LINQ的优化能力…对吧?
不正确的。直到您实际尝试迭代查询,查询提供程序才会尝试将IQueryable
转换为实际的数据库查询并执行它。当你有这样的内容:
var query = db.SomeTable;
你还没有获取整个表;您没有获取任何。如果你有:
var query2 = query.Where(item => item.SomeProperty == "someValue");
则查询提供程序将该过滤器应用于它发送给数据库的查询。
要很好地理解发生了什么,最简单/最好的方法是查看DB上下文的Log
值。它将准确地指示您何时执行查询,以及查询是什么。这样你就可以确保你在正确的时间执行了你应该执行的查询。