-
Expression.Invoke 用于子表达式;适用于 LINQ-to-SQL 和 LINQ-to-Objects,但不适用于 3.5SP1 中的 EF(对于 IEnumerable<T>,请先调用 .AsQueryable()):
Expression<Func<Customer, bool>> pred1 = cust=>cust.Country=="UK";
Expression<Func<Customer, bool>> pred2 = cust=>cust.Country=="France";
var param = Expression.Parameter(typeof(Customer), "x");
var final = Expression.Lambda<Func<Customer, bool>>(
Expression.OrElse(
Expression.Invoke(pred1, param),
Expression.Invoke(pred2, param)
), param);
using (var ctx = new DataClasses1DataContext())
{
ctx.Log = Console.Out;
int ukPlusFrance = ctx.Customers.Count(final);
}
示例 LINQ-to-SQL 输出(EF 在火花中爆炸):
SELECT COUNT(*) AS [value]
FROM [dbo].[Customers] AS [t0]
WHERE ([t0].[Country] = @p0) OR ([t0].[Country] = @p1)
-- @p0: Input NVarChar (Size = 2; Prec = 0; Scale = 0) [UK]
-- @p1: Input NVarChar (Size = 6; Prec = 0; Scale = 0) [France]
-
没有往返的身份管理器短路 - 即
var obj = ctx.Single(x=>x.Id == id);
var obj = ctx.Where(x=>x.Id == id).Single();
如果具有该身份的对象已经物化并存储在身份管理器中,等应该不需要进入数据库;也适用于First、SingleOrDefault、FirstOrDefault。请参阅 LINQ-to-SQL(也可以是 here 和 here;您可以通过附加到 .Log 进行验证);示例:
using (var ctx = new DataClasses1DataContext())
{
ctx.Log = Console.Out;
var first = ctx.Customers.First();
string id = first.CustomerID;
Console.WriteLine("Any more trips?");
var firstDup = ctx.Customers.First(x=>x.CustomerID==id);
Console.WriteLine(ReferenceEquals(first, firstDup)); // true
Console.WriteLine("Prove still attached");
int count = ctx.Customers.Count();
}
日志输出仅显示两次行程;一个用于第一次获取对象,一个用于计数;它还显示了物化器返回了相同的对象引用:
SELECT TOP (1) [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[
ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t
0].[Country], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.492
6
Any more trips?
True <==== this is object reference equality, not "are there any more trips"
Prove still attached
SELECT COUNT(*) AS [value]
FROM [dbo].[Customers] AS [t0]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.492
6
-
UDF 支持;举一个同样适用于 LINQ-to-Objects 的简单示例:
partial class MyDataContext {
[Function(Name="NEWID", IsComposable=true)]
public Guid Random() { return Guid.NewGuid();}
}
然后通过x => ctx.Random()订购;示例:
using (var ctx = new DataClasses1DataContext())
{
ctx.Log = Console.Out;
var anyAtRandom = (from cust in ctx.Customers
orderby ctx.Random()
select cust).First();
}
带输出:
SELECT TOP (1) [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 NEWID()
如果我感觉真的邪恶,recursive lambda;可能不值得以任何方式支持它...同样,4.0 表达式 (DLR) 节点类型。