创造一个参数等于对象的LINQ表达 [英] Creating a LINQ Expression where parameter equals object
问题描述
由于原始值年龄
我知道如何创建这样的表达式:
Given a primitive value age
I know how to create an expression like this:
//assuming: age is an int or some other primitive type
employee => employee.Age == age
这样做:
By doing this:
var entityType = typeof(Employee);
var propertyName = "Age";
int age = 30;
var parameter = Expression.Parameter(entityType, "entity");
var lambda = Expression.Lambda(
Expression.Equal(
Expression.Property(parameter, propertyName),
Expression.Constant(age)
)
, parameter);
除了在场景中有关财产和不断的是原始类型的正常工作。
That works fine except in scenarios where the property and constant in question are primitive types.
我将如何构建一个类似的表达如果比较对象之间
How would I construct a similar expression if the comparison is between objects?
使用EF我可以只写:
Location location = GetCurrentLocation();
employees = DataContext.Employees.Where(e => e.Location == location);
这也适用,但如果我尝试创建相同的表达式:
That also works, but if I try to create the same expression:
var entityType = typeof(Employee);
var propertyName = "Location";
var location = GetCurrentLocation();
var parameter = Expression.Parameter(entityType, "entity");
var lambda = Expression.Lambda(
Expression.Equal(
Expression.Property(parameter, propertyName),
Expression.Constant(location)
)
, parameter);
我得到一个错误,指出:
I get an error that says:
无法创建类型位置的恒定值。只有基本类型或枚举类型在这方面的支持。
我怀疑是 Expression.Constant()
只希望基本类型,所以我需要使用不同的表达工厂方法。 (maype Expression.Object
- 我知道,不存在)
My suspicion is that Expression.Constant()
only expects primitive types, so I need to use a different expression factory method. (maype Expression.Object
? - I know that doesn't exist)
有没有一种方法来创建一个表达式比较的对象?这是为什么EF能够正确解释它,如果它是一个编译的LINQ语句,但不是当它是一种表达?
Is there a way to create an expression that compares objects? Why is that EF is able to interpret it correctly if its a compiled LINQ statement, but not when it is an expression?
推荐答案
除了什么在以前的答案被提及。更具体的解决方案会去这样的:
In addition to what has been mentioned in previous answers. A more specific solution would go as such:
public static Expression CreateExpression<T>(string propertyName, object valueToCompare)
{
// get the type of entity
var entityType = typeof(T);
// get the type of the value object
var valueType = valueToCompare.GetType();
var entityProperty = entityType.GetProperty(propertyName);
var propertyType = entityProperty.PropertyType;
// Expression: "entity"
var parameter = Expression.Parameter(entityType, "entity");
// check if the property type is a value type
// only value types work
if (propertyType.IsValueType || propertyType.Equals(typeof(string)))
{
// Expression: entity.Property == value
return Expression.Equal(
Expression.Property(parameter, otherProperty),
Expression.Constant(valueToCompare)
);
}
// if not, then use the key
else
{
// get the key property
var keyProperty = propertyType.GetProperties().FirstOrDefault(p => p.GetCustomAttributes(typeof(KeyAttribute), false).Length > 0);
// Expression: entity.Property.Key == value.Key
Expression.Equal(
Expression.Property(
Expression.Property(parameter, entityProperty),
keyProperty
),
Expression.Constant(
keyProperty.GetValue(valueToCompare),
keyProperty.PropertyType
)
);
}
}
要点:
- 确保检查空
- 确保
属性类型
和VALUETYPE
是兼容的(无论他们是同一类型或可转换) - 若干假设这里做(如你做分配
KeyAttribute
) - 此代码没有进行测试,因此它是不完全复制/粘贴准备好了。
- Make sure to check for nulls
- Make sure
propertyType
andvalueType
are compatible (either they are the same type or are convertible) - Several assumptions are made here (e.g. that you do assign a
KeyAttribute
) - This code is not tested, so it is not exactly copy/paste ready.
希望有所帮助。
这篇关于创造一个参数等于对象的LINQ表达的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!