LINQ to Entities не распознает метод «System.Object GetValue (...)»

c# entity-framework-6 linq

Вопрос

Моя проблема в том, что мне нужно запросить значение свойства в родовом классе. Свойству отмечен атрибут.

См. Следующий код:

 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));

СтрокиKeyProperty и tenantKeyProperty имеют тип System.Reflection.PropertyInfo.

Я понимаю, почему я получаю ошибку. Когда запрос linq переводится на SQL, он не может понять свойство .GetValue.

Тем не менее, я полностью зациклен на работе здесь. Есть ли у кого-нибудь идеи, как достичь этого? Спасибо.

Принятый ответ

Вам нужно фактически создать объекты 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();

Популярные ответы

Приложение здесь ... После @Servy ответьте и на основе этой темы с хорошим ответом от @TomBrothers, вы можете использовать ту же логику, чтобы сделать функцию StartsWith (или аналогичную):

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 становится строкой.




Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему