使用Dynamic.cs动态构造Lambda 表达式

时间:2022-10-04 18:48:59

首先下载  Dynamic.cs 如果你不下载此代码,下面的例子将无法编译通过。

创建一个NorthWind 的对象模型。我们后面的查询语句都是基于此模型的。

NorthwindDataContext context = new NorthwindDataContext();

我们可以通过下面的语句来返回customers的所有记录。
var x = context.Customers. OrderByDescending(c => c.ContactName);

但是有时候我们需要动态的来决定排序的列,在我不了解动态Linq的时候我使用多个if判断的方式,或者switch方式。
当我了解了动态语句后发现我们其实可以这样来简单的实现。
string sortExpression = "ContactName DESC";
var x1 = context.Customers. OrderBy(sortExpression);

生成的SQL也跟我们想要的一样
SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], 
[t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
ORDER BY [t0].[ContactName] DESC

另外一个例子,如果我们有这样的一个语句
DateTime myDate = Convert.ToDateTime("7/26/1996");
var y = context. Orders.
Where(a => (a.Customer.Country == "Switzerland") && (a.OrderDate < myDate)).
OrderBy(o=> o.OrderDate).
Select(o => new { o.Customer.ContactName, o.Customer.Country, o.OrderDate });

我们可以这样来写

var y1 = context.
Orders.
Where("Customer.Country == @0 and OrderDate < @1", "Switzerland", myDate).
OrderBy("OrderDate").
Select("new(Customer.ContactName,Customer.Country, OrderDate)");
其中的@0,@1由,后面的参数代替。

执行语句
exec sp_executesql N'SELECT [t1].[ContactName], [t1].[Country], [t0].[OrderDate]
FROM [dbo].[Orders] AS [t0]
LEFT OUTER JOIN [dbo].[Customers] AS [t1] ON [t1].[CustomerID] = [t0].[CustomerID]
WHERE ([t1].[Country] = @p0) AND ([t0].[OrderDate] < @p1)
ORDER BY [t0].[OrderDate]'
N'@p0 nvarchar(11),@p1 datetime',
@p0=N'Switzerland',
@p1='1996-07-26 00:00:00:000'



后记: Dynamic.cs其实也没有什么特殊的奥秘,不过是使用了c#3.0提供的扩展方法,扩展了 DynamicQueryable的固有函数。使得where,orderby等可以直接将string作为参数,然后再把传入的字符串进行分析,最终通过 System.Linq.Expressions.Expression来实现动态Lambda 。倒是从这里我们可以更好的体会到扩展方法的含义。

相关文章