使用泛型类属性的LINQ表达式 [英] LINQ expression with generic class properties
问题描述
由于ID可以是长整型或者是长整型,也可以是长整型
<$ c我应该一般性地解决它。
我想出了以下内容: $ c> public static IEnumerable< T> GetModified< TId,T>(IQueryable T> objects,TId [] id)其中T:class
{
return objects.Where(j => ids.Contains((TId)j.GetType ().GetProperty( ID)的GetValue(J)));
}
不幸的是我收到了一个例外:
LINQ to Entities不识别方法'System.Object GetValue(System.Object)'方法,并且此方法不能转换为存储表达式。
异常是正常的,因为通过反射获取属性显然不能转换为SQL。 / p>
我会尝试的一件事是创建一个通用接口,该接口公开给定类型的 Id
属性:
public interface HasId< T> {
T Id {get;组; }
}
现在你可以声明你的实体实现 HasId< ;例如,如果
p> Id
类型为 int
,则int>
下一步是修改您的方法,如下所示:
public static IEnumerable的< T> GetModified< TId,T>
(IQueryable< T>对象,TId [] id)其中T:class,HasId< TId>
{
return objects.Where(j => ids.Contains(j.Id));
$ / code>
请注意添加的通用限制:其中T:class ,HasId< TId>
。这使您可以编写简化的 j.Id
,它将返回 TId
值,而不是采用反射。 / p>
请注意,我没有运行或测试此代码;这只是一个想法,当我看到你的问题时,我希望它有帮助。
更新:
这是另一种可能的解决方案,它不需要声明接口或以任何方式更改类:
public static IEnumerable< T> ; GetModified< TId,T>
(IQueryable< T>对象,TId [] id,表达式< Func< T,TId>> idSelector)
其中T:class
{
return objects.Where j => ids.Contains(idSelector(j)));
}
我在这里完成的是添加 Expression< ; Func< T,TId>> idSelector
参数,该表达式可以返回 T
给定实例的 Id
。
您可以这样调用方法:
var modified = GetModified(dbObjects,yourIdArray,entity => entity.Id);
(只有第三个参数是新的;现在保留其他参数)。
再一次,我还没有测试过这个工作是否正常,甚至没有编译,因为我在这里没有带有VS的计算机:(。
)I would like to pass an IQueryable and an array of ids to a method which filters the IQueryable based on those ids.
As the ids can be either long's or int's it should be solved generically.
I came up with the following:
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)));
}
Unfortunately I'm getting the exception:
LINQ to Entities does not recognize the method 'System.Object GetValue(System.Object)' method, and this method cannot be translated into a store expression.
The exception is normal, as getting properties through reflection is something that clearly cannot be translated to SQL.
One thing I would try is to create a generic interface that exposes an Id
property of a given type:
public interface HasId<T> {
T Id { get; set; }
}
Now you could declare your entity as implementing HasId<int>
, for example, if the Id
was of type int
.
The next step is to modify your method like so:
public static IEnumerable<T> GetModified<TId, T>
(IQueryable<T> objects, TId[] ids) where T : class, HasId<TId>
{
return objects.Where(j => ids.Contains(j.Id));
}
Note the added generic restriction: where T : class, HasId<TId>
. This enables you to write the simplified j.Id
, which returns a TId
value, instead of resorting to reflection.
Please note that I haven't run or tested this code; it's just an idea that I got when I saw your problem and I hope it helps.
Update:
Here's another possible solution that doesn't require that you declare interfaces or change your classes in any way:
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)));
}
What I've done here is add the Expression<Func<T, TId>> idSelector
parameter, an expression that can return the Id
of a given instance of T
.
You would call the method like that:
var modified = GetModified(dbObjects, yourIdArray, entity => entity.Id);
(only the third parameter being new; keep the others as you have them now).
Again, I haven't tested if this works or even compiles, as I don't have a computer with VS here :(.
这篇关于使用泛型类属性的LINQ表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!