Reputation: 57
I'm using a expression as parameter for inserting data (with 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);
}
I have a method nammed Synchronize with a different expression :
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<XContext, T>())
{
list.ForEach(x =>
{
repo.AddIfNotExists(x, y => predicate.Compile().Invoke(x, y));
});
repo.Save();
}
}
I need two parameters for my method Synchronize :
Synchronize<ClientLivraison>("clientlivraison", (x, y) => x.IdClientJuridique == y.IdClientJuridique && x.IdClientLivraison == y.IdClientLivraison);
At runtime, I have this exception :
System.NotSupportedException : 'LINQ to Entities does not recognize the method 'Boolean Invoke(X.X.SynchroDb.Entity.Origine, X.X.SynchroDb.Entity.Origine)' method, and this method cannot be translated into a store expression.'
My question, how convert/pass my expression
Expression<Func<T, T, bool>>
To
Expression<Func<T, bool>>
Upvotes: 1
Views: 221
Reputation: 205539
It is possible to convert Expression<Func<T, T, bool>>
to Expression<Func<T, bool>>
by replacing the first or second parameter using custom ExpressionVisitor
and Expression.Lambda
method.
But the easier and more natural way would be to change the Synchronize
method argument
Expression<Func<T, T, bool>> predicate
to
Func<T, Expression<Func<T, bool>>> predicateFactory>
i.e. a function delegate with parameter T
, which when invoked returns Expression<Func<T, bool>>
based on the passed argument.
From the caller perspective, it would be a matter of changing
(x, y) => x.IdClientJuridique == y.IdClientJuridique && x.IdClientLivraison == y.IdClientLivraison
to
x => y => x.IdClientJuridique == y.IdClientJuridique && x.IdClientLivraison == y.IdClientLivraison
and the implementation would be simply replacing
repo.AddIfNotExists(x, y => predicate.Compile().Invoke(x, y));
with
repo.AddIfNotExists(x, predicateFactory(x));
Here is the whole method:
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();
}
}
Upvotes: 2