C# 具有泛型类属性的LINQ表达式
我想将一个IQueryable和一个ID数组传递给一个基于这些ID过滤IQueryable的方法 由于ID可以是long或int,因此应该一般地解决它 我得出了以下结论:C# 具有泛型类属性的LINQ表达式,c#,linq,generics,lambda,C#,Linq,Generics,Lambda,我想将一个IQueryable和一个ID数组传递给一个基于这些ID过滤IQueryable的方法 由于ID可以是long或int,因此应该一般地解决它 我得出了以下结论: public static IEnumerable<T> GetModified<TId, T>(IQueryable<T> objects, TId[] ids) where T : class { return objects.Where(j => ids.Cont
public static IEnumerable<T> GetModified<TId, T>(IQueryable<T> objects, TId[] ids) where T : class
{
return objects.Where(j => ids.Contains((TId)j.GetType().GetProperty("Id").GetValue(j)));
}
公共静态IEnumerable GetModified(IQueryable对象,TId[]id),其中T:class
{
返回objects.Where(j=>ids.Contains((TId)j.GetType().GetProperty(“Id”).GetValue(j));
}
不幸的是,我得到了一个例外:
LINQ to Entities无法识别方法“System.Object GetValue(System.Object)”方法,并且无法将此方法转换为存储表达式
实体框架不支持某些.NET方法,例如
GetValue()
,因为它不转换为SQL(这是实际执行到IQueryable
的代码)。在执行反射之前,请尝试调用ToList
以获取CLR对象:
public static IEnumerable<T> GetModified<TId, T>(IQueryable<T> objects, TId[] ids) where T : class
{
return objects.ToList().Where(j => ids.Contains((TId)j.GetType().GetProperty("Id").GetValue(j)));
}
公共静态IEnumerable GetModified(IQueryable对象,TId[]id),其中T:class
{
返回objects.ToList(),其中(j=>ids.Contains((TId)j.GetType().GetProperty(“Id”).GetValue(j));
}
异常是正常的,因为通过反射获取属性显然无法转换为SQL
我要尝试的一件事是创建一个通用接口,该接口公开给定类型的Id
属性:
public interface HasId<T> {
T Id { get; set; }
}
注意添加的通用限制:其中T:class,HasId
。这使您能够编写简化的j.Id
,它返回一个TId
值,而不是诉诸反射
请注意,我没有运行或测试这段代码;这只是我在看到您的问题时得到的一个想法,我希望它能有所帮助
更新:
下面是另一个可能的解决方案,它不需要您以任何方式声明接口或更改类:
public static IEnumerable<T> GetModified<TId, T>
(IQueryable<T> objects, TId[] ids, Expression<Func<T, TId>> idSelector)
where T : class
{
return objects.Where(j => ids.Contains(idSelector(j)));
}
(只有第三个参数是新的;保持其他参数不变)
再说一次,我还没有测试它是否有效,甚至没有编译,因为我这里没有一台装有VS的计算机:(.这是可行的,但效率非常低,因为所有对象都是从数据库中提取的,对吗?这是正确的。但由于您需要反射,LINQ-to-Entite无法将反射代码转换为SQL。我想您可以尝试
objects.Cast()。其中(a=>ids.Contains(a.Id))
亲爱的先生,这是一个很好的答案!我没有尝试第二种方法,但第一种方法很有效。第二种方法没有达到预期效果。错误:“idSelector”是一个变量,但用作方法。我问了另一个与第二种方法相关的问题。如果您感兴趣,请参阅
public static IEnumerable<T> GetModified<TId, T>
(IQueryable<T> objects, TId[] ids, Expression<Func<T, TId>> idSelector)
where T : class
{
return objects.Where(j => ids.Contains(idSelector(j)));
}
var modified = GetModified(dbObjects, yourIdArray, entity => entity.Id);