c# – LINQ-to-SQL:将Func转换为表达式>
LINQ-to-SQL一直是我的PITA.我们使用它与数据库进行通信,然后通过WCF将实体发送到Silverlight应用程序.一切都运行正常,直到开始编辑(CUD)实体及其相关数据.
我终于能够设计两个允许CUD的for循环.我试着重构它们,而我非常接近,直到我得知我不能总是用L2S做Lambda. public static void CudOperation<T>(this DataContext ctx,IEnumerable<T> oldCollection,IEnumerable<T> newCollection,Func<T,T,bool> predicate) where T : class { foreach (var old in oldCollection) { if (!newCollection.Any(o => predicate(old,o))) { ctx.GetTable<T>().DeleteAllOnSubmit(ctx.GetTable<T>().Where(o => predicate(old,o))); } } foreach (var newItem in newCollection) { var existingItem = oldCollection.SingleOrDefault(o => predicate(o,newItem)); if (existingItem != null) { ctx.GetTable<T>().Attach(newItem,existingItem); } else { ctx.GetTable<T>().InsertOnSubmit(newItem); } } } 被称为: ctx.CudOperation<MyEntity>(myVar.MyEntities,newHeader.MyEntities,(x,y) => x.PkID == y.PkID && x.Fk1ID == y.Fk1ID && x.Fk2ID == y.FK2ID); 这几乎奏效了.但是,我的Func需要是一个表达式>,这就是我被困的地方. 有没有人可以告诉我这是否可能?由于SharePoint 2010,我们必须使用.NET 3.5. 解决方法
只需更改参数:
Func<T,bool> predicate 至: Expression<Func<T,bool>> predicate 表达式由编译器生成. 现在,问题是如何使用它. 在您的情况下,您需要一个Func和一个表达式,因为您在Enumerable LINQ查询(基于func)以及SQL LINQ查询(基于表达式)中使用它. 在: .Where(o => predicate(old,o)) 旧参数是固定的.所以我们可以将参数更改为: Func<T,Expression<Func<T,bool>>> predicate 这意味着我们可以提供一个参数(‘固定’一个)并返回一个表达式. foreach (var old in oldCollection) { var condition = predicate(old); // ... { ctx.GetTable<T>().DeleteAllOnSubmit(ctx.GetTable<T>().Where(condition)); } } 我们还需要在Any中使用它.要从表达式获取Func,我们可以调用Compile(): foreach (var old in oldCollection) { var condition = predicate(old); if (!newCollection.Any(condition.Compile())) { ctx.GetTable<T>().DeleteAllOnSubmit(ctx.GetTable<T>().Where(condition)); } } 你可以用下一部分做同样的事情. 有两个问题: >使用Compile()批次可能会影响性能.我不确定它实际会产生多大的影响,但我会对其进行分析以进行检查. 可能有更好的方法来做到这一点:) 这是另一种方法,它应该更快一些,因为Expression只需要编译一次.创建一个“应用”一个参数的重写器,如下所示: class PartialApplier : ExpressionVisitor { private readonly ConstantExpression value; private readonly ParameterExpression replace; private PartialApplier(ParameterExpression replace,object value) { this.replace = replace; this.value = Expression.Constant(value,value.GetType()); } public override Expression Visit(Expression node) { var parameter = node as ParameterExpression; if (parameter != null && parameter.Equals(replace)) { return value; } else return base.Visit(node); } public static Expression<Func<T2,TResult>> PartialApply<T,T2,TResult>(Expression<Func<T,TResult>> expression,T value) { var result = new PartialApplier(expression.Parameters.First(),value).Visit(expression.Body); return (Expression<Func<T2,TResult>>)Expression.Lambda(result,expression.Parameters.Skip(1)); } } 然后像这样使用它: public static void CudOperation<T>(this DataContext ctx,bool>> predicate) where T : class { var compiled = predicate.Compile(); foreach (var old in oldCollection) { if (!newCollection.Any(o => compiled(o,old))) { var applied = PartialApplier.PartialApply(predicate,old); ctx.GetTable<T>().DeleteAllOnSubmit(ctx.GetTable<T>().Where(applied)); } } foreach (var newItem in newCollection) { var existingItem = oldCollection.SingleOrDefault(o => compiled(o,existingItem); } else { ctx.GetTable<T>().InsertOnSubmit(newItem); } } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |