Reputation: 11177
I have extension method that has the following signature:
public static class GenericSeeder
{
public static void Seed<TSeed, TEntity>(this DbContext context, IEnumerable<TSeed> seeds, Expression<Func<TEntity, TSeed, bool>> predicate)
{
// code that I'm looking for goes here
}
}
To have better understanding of what the method is doing, here's how it should be used:
context.Seed<SeedClass, EntityClass>(seeds, (entity, seed) => entity.Name == seed.OtherProperty);
So basically, I am using the predicate to check whether the seed was already applied. However, in order to do a check, I must use Where or FirstOrDefault from Linq to Entities, which takes the following as parameter:
Expression<Func<TEntity, bool>> predicate
So my lambda expression is function of 2 IN parameters (TSeed, TEntity) and 1 OUT parameter (bool). I need to iterate through provided collection of TSeed objects, and for each of those, use that object as parameter for my lambda expression, to generate LINQ 2 Entities lambda expression which has 1 IN parameter (TEntity) and 1 OUT parameter (bool).
Is there a way to do a partial invoke of lambda expression / func to get another lambda expression / func?
Upvotes: 1
Views: 626
Reputation: 203829
Through the use of LINQKit to allow expressions to be invoked in such a way that they will be transformed into other expressions the implementation of your method becomes fairly trivial:
public static IQueryable<TEntity> Seed<TSeed, TEntity>(
this DbContext context,
IEnumerable<TSeed> seeds,
Expression<Func<TEntity, TSeed, bool>> predicate)
{
return context.Set<TEntity>()
.AsExpandable()
.Where(entity => seeds.Any(seed => predicate.Invoke(entity, seed)));
}
Upvotes: 1
Reputation: 11177
I've managed to create solution on my own. I did however use the infamous LinqKit extension library and it's AsExpandable() extension method.
LinqKit can be found here: NuGet link
So this is the implementation that works with Linq 2 Entities:
public static void Seed<TSeed, TEntity>(this DbContext context, IEnumerable<TSeed> seeds, Expression<Func<TEntity, TSeed, bool>> predicate)
where TEntity : class
where TSeed : class
{
foreach (TSeed seed in seeds)
{
Expression<Func<TEntity, bool>> matchExpression = (entity) => predicate.Invoke(entity, seed);
TEntity existing = context.Set<TEntity>().AsExpandable().FirstOrDefault(matchExpression);
// Rest of code is omitted as it is not related to the original question.
// The query above is properly executed by Linq 2 Entities.
}
}
Upvotes: 0
Reputation: 8099
I have no idea what you are doing, but this is how you do partial application in c#:
Func<int,bool, string> twoInFunc= (int a, bool b) => a.ToString() + b.ToString();
int number = 7;
Func<bool, string> oneInFunc= (bool b) => twoInFunc(number,b);
Upvotes: 0