LINQ to Entities无法识别方法'System.Object GetValue(...)'

时间:2014-02-28 19:21:39

标签: c# linq entity-framework-6

我的问题是我需要查询泛型类中属性的值。该属性标有属性。

请参阅以下代码:

 var rowKeyProperty = EFUtil.GetClassPropertyForRowKey<T>();
 var tenantKeyProperty = EFUtil.GetClassPropertyForTenantKey<T>();

 var queryResult =
                objContext.CreateObjectSet<T>().Single(l => (((int) tenantKeyProperty.GetValue(l, null)) == tenantKey) &&
                                                            (((int)rowKeyProperty.GetValue(l, null)) == KeyValue));

rowKeyProperty和tenantKeyProperty的类型为System.Reflection.PropertyInfo。

我理解为什么我收到错误。当linq查询转换为SQL时,它无法理解property.GetValue。

但是,我对这里的工作感到非常难过。有没有人有任何想法如何实现这一目标? THX。

4 个答案:

答案 0 :(得分:19)

您需要实际构建Expression个对象来表示您希望它模仿的表达式,在这种情况下,您要表示的表达式是:

l => l.SomeProperty == SomeValue

因此,您需要逐位构建该组件的每个组件,从创建参数,定义相等运算符,属性访问,常量值等。

public static Expression<Func<TItem, bool>> PropertyEquals<TItem, TValue>(
    PropertyInfo property, TValue value)
{
    var param = Expression.Parameter(typeof(TItem));
    var body = Expression.Equal(Expression.Property(param, property),
        Expression.Constant(value));
    return Expression.Lambda<Func<TItem, bool>>(body, param);
}

完成所有这些后,您可以使用您拥有的数据来调用它:

var queryResult = objContext.CreateObjectSet<T>()
    .Where(PropertyEquals<T, int>(tenantKeyProperty, tenantKey))
    .Where(PropertyEquals<T, int>(rowKeyProperty, KeyValue))
    .Single();

答案 1 :(得分:3)

此处的附录...在@Servy回答并基于this主题和@TomBrothers的一个很好的答案之后,您可以使用相同的逻辑来创建StartsWith(或类似)函数:< / p>

public static Expression<Func<TItem, bool>> PropertyStartsWith<TItem>(PropertyInfo propertyInfo, string value)
{
    var param = Expression.Parameter(typeof(TItem));

    var m = Expression.MakeMemberAccess(param, propertyInfo);
    var c = Expression.Constant(value, typeof(string));
    var mi = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
    var body = Expression.Call(m, mi, c);

    return Expression.Lambda<Func<TItem, bool>>(body, param);
}

在这种情况下,它强制value为字符串。

答案 2 :(得分:1)

Expression.Constant(value,typeof(TValue)))中指定类型更正确

public static Expression<Func<TItem, bool>> PropertyEquals<TItem, TValue>(
        string property, TValue value)
    {
        var xParameter = Expression.Parameter(typeof(TItem));
        var body = Expression.Equal(Expression.Property(xParameter, property), Expression.Constant(value, typeof(TValue)));
        return Expression.Lambda<Func<TItem, bool>>(body, xParameter);
    }

或者像这样检查属性。 ChangeType

public static Expression<Func<TItem, bool>> PropertyEquals<TItem, TValue>(
        string property, TValue value)
    {
        var xParameter = Expression.Parameter(typeof(TItem));
        var type = typeof(TItem).GetProperty(property).PropertyType;
        value = ChangeType<TValue>(value);
        BinaryExpression body = Expression.Equal(Expression.Property(xParameter, property), Expression.Constant(value, type));

        return Expression.Lambda<Func<TItem, bool>>(body, xParameter);
    }

它是做什么用的。我检查所有对类的类引用,寻找“ ..ID”条目。在某个地方,我的类型为“ int”和“ int?”。

public class BudgetLimit : BaseRecord
{
    [Required]
    public int DepartmentID { get; set; } 
    public virtual Department Department { get; set;}

    public int? ProjectID { get; set; }
    public virtual Project Project { get; set; }
 }

答案 3 :(得分:0)

您在LINQ语句后添加.AsEnableable。 例如objectdata.AsEnumerable() enter link description here