Benbirleştiren birden ifadeler ağaçlar
parametre 'p' varlıkları için belirlenen LINQ sorgu ifadesi de bağlı değildi aşağıdaki hatayı alıyorum.
Sorunu (ParameterExpression
aynı örneği ağacındaki bütün ifadeler kullanılmalıdır) anlamak ve çözümler online ama hiç şans ile buldum kullanmaya çalıştılar.
Bu
benim yöntemprivate void SeedEntity<TEntity>(DatabaseContext context, ref TEntity entity, params Expression<Func<TEntity, object>>[] identifierExpressions) where TEntity : class
{
Expression<Func<TEntity, bool>> allExpresions = null;
var parameters = identifierExpressions.SelectMany(x => x.Parameters).GroupBy(x => x.Name).Select(p => p.First()).ToList();
foreach (Expression<Func<TEntity, object>> identifierExpression in identifierExpressions)
{
Func<TEntity, object> vv = identifierExpression.Compile();
object constant = vv(entity);
ConstantExpression constExp = Expression.Constant(constant, typeof(object));
BinaryExpression equalExpression1 = Expression.Equal(identifierExpression.Body, constExp);
Expression<Func<TEntity, bool>> equalExpression2 = Expression.Lambda<Func<TEntity, bool>>(equalExpression1, parameters);
if (allExpresions == null)
{
allExpresions = equalExpression2;
}
else
{
BinaryExpression bin = Expression.And(allExpresions.Body, equalExpression2.Body);
allExpresions = Expression.Lambda<Func<TEntity, bool>>(bin, parameters);
}
}
TEntity existingEntity = null;
if (allExpresions != null)
{
existingEntity = context.Set<TEntity>().FirstOrDefault(allExpresions);
}
if (existingEntity == null)
{
context.Set<TEntity>().Add(entity);
}
else
{
entity = existingEntity;
}
}
Bu özellikleri bir dizi dayalı bir varlığın arama için bir ifade oluşturur olduğunu.
Tek bir ifade için iyi çalışıyor, hata yalnızca birden çok iletimde gerçekleşiyor. Böyle denilen
: Bir ConstantExpression
yapabilirsiniz ile
context.Set<TEntity>().FirstOrDefault(p=>p.Name == e.Name && p.Age == e.Age);
değiştirilmesi e.Name & & e.Age:
SeedEntity(context, ref e, p=> p.Name);//Works
SeedEntity(context, ref e, p=> p.Name, p=> p.Age);//Fails
Aşağıdaki gerçekleştirerek bana benzer bir şey üretir Yukarıdaki yönteme bakın, tüm benzersiz paramları yakalayın ve bunları parameters
'da saklayın. p, daha sonra aynı değişkeni kullanın.Bu başlangıçtır, ancak params
dizisi olarak geçirilen Expression<Func<TEntity, bool>>
dizisinin her birindeki parametrelerin örneklerini değiştirmem gerekiyor; bu, başarısız olduğum yer.
Ben ifadeleri numaralandırmak ve ben de ExpressionVisitor
public class ExpressionSubstitute : ExpressionVisitor
{
public readonly Expression from, to;
public ExpressionSubstitute(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
if (node == from) return to;
return base.Visit(node);
}
}
public static class ExpressionSubstituteExtentions
{
public static Expression<Func<TEntity, TReturnType>> RewireLambdaExpression<TEntity, TReturnType>(Expression<Func<TEntity, TReturnType>> expression, ParameterExpression newLambdaParameter)
{
var newExp = new ExpressionSubstitute(expression.Parameters.Single(), newLambdaParameter).Visit(expression);
return (Expression<Func<TEntity, TReturnType>>)newExp;
}
}
Sadece hızlı bir düşünce, ikinci parametre için farklı bir harf kullanmayı denediniz mi? (örn. p => p.Adı, f => f.Age) –
Girdiğiniz için bu, asla işe yaramaz, çünkü sadece bir parametreniz var, ancak ikisini geçiyorsunuz. Lambda –
için verilen hatalı parametre sayısını atayacaktır. Sorguları birleştirmek yerine neden bunları arka arkaya uygulamıyorsunuz? 'results =/* Tam set * /; foreach (ifade) {results = sonuçlar.Where (expression)} '? EF, “IQueryable” ı kullandığı için, çerçeve gerekli olana kadar yürütmeyi erteler, ardından tüm yüklemleri SQL için tek bir sorguda birleştirir. – Basic