簡體   English   中英

在Linq中使用反射和Lambda表達式

[英]Use reflection and lambda expression with linq

我需要verifing標志命名的值篩選項目的集合deletion_date

 public List<T> GetAll()
 {
   if (context == null) context = new ajtdevEntities();
   return context.Set<T>().Where(p => p.GetType().GetProperty("deletion_date") == null).ToList();
 }

使用此通用方法時出現異常

LINQ to Entities無法識別方法'System.Reflection.PropertyInfo GetProperty(System.String)',后者無法轉換為術語存儲。

如何解決此方法?

您可以使用System.Linq.Expressions這樣手動構建篩選器表達式,而不是反射:

public List<T> GetAll<T>()
{
    var parameter = Expression.Parameter(typeof(T), "p");
    var predicate = Expression.Lambda<Func<T, bool>>(
        Expression.Equal(Expression.PropertyOrField(parameter, "deletion_date"), Expression.Constant(null)),
        parameter);
    if (context == null) context = new ajtdevEntities();
    return context.Set<T>().Where(predicate).ToList();
}

請注意,如果您的類型沒有名為“ deletion_date”的屬性/字段,或者該屬性的類型不支持null ,則上述內容將引發異常。 但是對於基於反射的實現(如果可行)也可以這樣說。

ORM將檢查lambda並將其部分轉換為SQL。 實體框架團隊選擇不支持反思,這是正確的。 因此它無法將GetProperty()調用轉換為SQL,因此會出現錯誤。

無論如何,它將無法正常工作,因為GetProperty()獲取的是PropertyInfo實例,而不是值。 因此,如果為null ,則表明p的類型沒有名為deletion_date屬性。

正確的方法是在PropertyInfo上調用GetValue() (請注意,如果沒有這樣命名的PropertyInfo ,這將引發NullReferenceException ):

p => p.GetType().GetProperty("deletion_date").GetValue(p)

但是同樣,實體框架不支持反射,因此您要使用接口:

public interface IDeletable
{
    DateTime? deletion_date { get; set; }
}

並將其作為一般約束應用於您的類或方法。 然后,您可以在lambda中使用它:

public class WhateverClass<T>
    where T : IDeletable
{
    public List<T> GetAll()
    {
        return context.Set<T>().Where(p => p.deletion_date == null).ToList();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM