我使用表达式作为插入数据的参数(使用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);
}
我有一个方法nammed使用不同的表达式进行同步:
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>>
答案 0 :(得分:1)
可以使用自定义ExpressionVisitor
和Expression.Lambda
方法替换第一个或第二个参数,将Expression<Func<T, T, bool>>
转换为Expression<Func<T, bool>>
。
但更简单,更自然的方法是更改Synchronize
方法参数
Expression<Func<T, T, bool>> predicate
到
Func<T, Expression<Func<T, bool>>> predicateFactory>
即。一个带参数T
的函数委托,调用时会根据传递的参数返回Expression<Func<T, bool>>
。
从调用者的角度来看,这将是一个改变的问题
(x, y) => x.IdClientJuridique == y.IdClientJuridique && x.IdClientLivraison == y.IdClientLivraison
到
x => y => x.IdClientJuridique == y.IdClientJuridique && x.IdClientLivraison == y.IdClientLivraison
并且实施将简单地替换
repo.AddIfNotExists(x, y => predicate.Compile().Invoke(x, y));
与
repo.AddIfNotExists(x, predicateFactory(x));
以下是整个方法:
protected void Synchronize<T>(string resource, Func<T, Expression<Func<T, bool>>> predicateFactory) where T : class
{
var list = _context.RestClient.Get<List<T>>(resource);
using (var repo = new Repository<GmaoContext, T>())
{
list.ForEach(x =>
{
repo.AddIfNotExists(x, predicateFactory(x));
});
repo.Save();
}
}