【发布时间】:2017-04-24 15:50:27
【问题描述】:
我使用表达式作为插入数据的参数(使用 EF):
public bool Exists(Expression<Func<V, bool>> predicate)
{
return _dbContext.Set<V>().Any(predicate);
}
public void AddIfNotExists(V entity, Expression<Func<V, bool>> predicate)
{
if (!Exists(predicate))
Add(entity);
}
我有一个名为 Synchronize 的方法,使用不同的表达式:
protected void Synchronize<T>(string resource, Expression<Func<T, T, bool>> predicate) where T : class
{
var list = _context.RestClient.Get<List<T>>(resource);
using (var repo = new Repository<GmaoContext, T>())
{
list.ForEach(x =>
{
repo.AddIfNotExists(x, y => predicate.Compile().Invoke(x, y));
});
repo.Save();
}
}
我的方法 Synchronize 需要两个参数:
Synchronize<ClientLivraison>("clientlivraison", (x, y) => x.IdClientJuridique == y.IdClientJuridique && x.IdClientLivraison == y.IdClientLivraison);
在运行时,我有这个异常:
System.NotSupportedException:'LINQ to Entities 无法识别方法 'Boolean Invoke(Manuloc.Gmao.SynchroDb.Entity.Origine, Manuloc.Gmao.SynchroDb.Entity.Origine)' 方法,并且此方法不能被翻译成商店表达式。'
我的问题,如何转换/传递我的表达式
Expression<Func<T, T, bool>>
到
Expression<Func<T, bool>>
【问题讨论】:
-
您没有 LINQ 表达式作为参数,您只有一个表达式。它绝不是 LINQ 特有的。
-
LINQ to EF query 被转换为 SQL。您使用的 lambda 和表达式不会被执行,它们会被转换为 SQL。该错误表明您提供的 lambda 无法 被转换为 SQL。具体来说,
Compile().Invoke()无法转换为 SQL。只需删除它。 -
如果我删除 Compile().Invoke(),
repo.AddIfNotExists(x, y => func(x, y));我有一个例外:'LINQ to Entities 不支持 LINQ 表达式节点类型'Invoke'. -
您的代码可能存在比相等比较的性能更严重的性能问题。通过在这样的循环中调用
AddIfNotExists,您可能正在执行 N 个单独的命令,从而导致 N 次到数据库的往返。这会导致延迟 和 过多的登录 - 最坏的情况,慢 N 倍。 EF 已经支持附加分离的实体 -
@SpeedNeo 那么您必须拨打任何其他
Invoke()电话。这些不是自己出现的。无论如何,您的代码是将新项目添加到上下文的一种相当复杂的方式。 PSWHERE子句由.Where()调用生成。你没有这样的电话。你的AddIfNotExists试图模仿Where(predicate)
标签: c# entity-framework linq-to-entities