Tôi nhận được lỗi sauKết hợp nhiều biểu thức cây
Tham số 'p' không bị ràng buộc trong LINQ to Entities định biểu thức truy vấn.
Tôi hiểu vấn đề (giống trường hợp của ParameterExpression
nên được sử dụng với tất cả các biểu thức trong cây) và đã cố gắng sử dụng các giải pháp tôi đã tìm thấy trực tuyến nhưng không có may mắn.
Đây là phương pháp của tôi
private 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;
}
}
Nó tạo ra một biểu hiện cho việc tra cứu của một thực thể dựa trên một số tài sản.
Nó hoạt động tốt cho một biểu thức duy nhất, lỗi chỉ xảy ra khi truyền trong nhiều.
gọi là như thế này:
SeedEntity(context, ref e, p=> p.Name);//Works
SeedEntity(context, ref e, p=> p.Name, p=> p.Age);//Fails
Nó tạo ra một cái gì đó tương tự như tôi thực hiện như sau:
context.Set<TEntity>().FirstOrDefault(p=>p.Name == e.Name && p.Age == e.Age);
Thay e.Name & & e.Age với một ConstantExpression
Bạn có thể xem trong phương pháp trên, tôi lấy tất cả các thông số duy nhất và lưu trữ chúng trong parameters
tại p, sau đó sử dụng cùng một biến trong suốt.Đây là sự bắt đầu, nhưng sau đó tôi cần phải thay thế các trường hợp của tham số trong mỗi Expression<Func<TEntity, bool>>
được chuyển thành mảng params
, đây là nơi tôi đang thất bại.
Tôi đã thử liệt kê các từ ngữ và sử dụng các phương pháp .Update()
qua trong params
Tôi cũng đã thử một giải pháp sử dụng các 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;
}
}
Chỉ cần suy nghĩ nhanh, bạn đã thử sử dụng một chữ cái khác cho tham số thứ hai chưa? (tức là p => p.Name, f => f.Age) –
Cảm ơn bạn đã nhập, thao tác này sẽ không bao giờ hoạt động, vì bạn chỉ có một tham số nhưng bạn chỉ có một tham số. Nó sẽ ném số thông số không chính xác được cung cấp cho lambda –
Thay vì kết hợp các truy vấn, tại sao không áp dụng chúng liên tục? 'results =/* Toàn bộ * /; foreach (expression) {results = results.Where (expression)} '? Vì EF sử dụng 'IQueryable', khung công tác sẽ hoãn thực thi cho đến khi cần thiết, sau đó kết hợp tất cả các biến vị ngữ thành một truy vấn duy nhất cho SQL. – Basic