是否可以将linq查询的一部分传递给函数?我想为我的DAL创建一个通用接口,它始终使用相同的查询接口.例如,
ListGet(Join j, Where w, Select s){ return currentDataContext .Join(j).Where(w).Select(s).ToList(); }
这种事情有可能吗?我认为它将用表达式树完成,但我无法找到它的例子.
好吧,"加入"很棘手,因为很难表达一个连接 - 但像/ select/orderby这样的东西很容易......
实际上,它只是一种结合各种LINQ方法的情况IQueryable
,通常接受Expression
某种组合.因此,带有可选谓词的基本选择将是:
public IQueryableGet ( Expression > predicate ) where T : class { IQueryable query = (IQueryable )GetTable(typeof(T)); if (predicate != null) query = query.Where(predicate); return query; }
我也倾向于回归IQueryable
,因为那是完全可组合的.如果调用者想要一个列表,他们总是可以使用ToList()
它......或者(例如):
using(var ctx = new MyDataContext(CONN)) { ctx.Log = Console.Out; int frCount = ctx.Get(c => c.Country == "France").Count(); }
哪个(使用Northwind)执行查询:
SELECT COUNT(*) AS [value] FROM [dbo].[Customers] AS [t0] WHERE [t0].[Country] = @p0
在查询中包含"选择"(投影)的问题是您最终会得到多个泛型类型.由于您经常希望投影是匿名类型,因此很难指定投影类型(匿名)和表类型,并且它不可调用.
实际上,我想知道编写这样的方法是否有很多好处.我可能会坚持使用基本方法:
public IQueryableGet () where T : class { return (IQueryable )GetTable(typeof(T)); }
让调用者以他们喜欢的方式组成它 - 可能使用查询语法:
var list = (from cust in ctx.Get() where cust.Country == "France" select cust.CompanyName).Take(10).ToList();
用途:
SELECT TOP (10) [t0].[CompanyName] FROM [dbo].[Customers] AS [t0] WHERE [t0].[Country] = @p0
或者,如果您确实想要包含order by和projection,那么扩展方法是最实用的方法; 那么你不需要指定原始(源)T(当与anon类型混合时,它是不可调用的):
public static class QueryExtension { public static IQueryableGet ( this IQueryable source, Expression > where, // optional Expression > select, Expression > orderBy) { if (where != null) source = source.Where(where); return source.Select(select).OrderBy(orderBy); } }
然后考虑一个DAL方法,例如:
public ListCountries() { return Customers.Get( x=>x.CompanyName != "", x=>x.Country, x=>x).Distinct().ToList(); }
使用(再次,使用Northwind):
SELECT DISTINCT [t0].[Country] FROM [dbo].[Customers] AS [t0] WHERE [t0].[CompanyName] <> @p0