nik*_*klr 4 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.Contains((TId)j.GetType().GetProperty("Id").GetValue(j)));
}
Run Code Online (Sandbox Code Playgroud)
不幸的是我得到了例外:
LINQ to Entities无法识别方法'System.Object GetValue(System.Object)'方法,并且此方法无法转换为存储表达式.
异常是正常的,因为通过反射获取属性显然无法转换为SQL.
我要尝试的一件事是创建一个公开接口,公开Id
给定类型的属性:
public interface HasId<T> {
T Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以将实体声明为实现HasId<int>
,例如,如果Id
是类型int
.
下一步是修改你的方法,如下所示:
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));
}
Run Code Online (Sandbox Code Playgroud)
请注意添加的通用限制:where T : class, HasId<TId>
.这使您可以编写简化的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)));
}
Run Code Online (Sandbox Code Playgroud)
我在这里做的是添加Expression<Func<T, TId>> idSelector
参数,一个可以返回Id
给定实例的表达式T
.
你可以这样调用这个方法:
var modified = GetModified(dbObjects, yourIdArray, entity => entity.Id);
Run Code Online (Sandbox Code Playgroud)
(只有第三个参数是新的;保留现在的其他参数).
再说一遍,我没有测试过这是否有效甚至是编译,因为我这里没有配备VS的电脑:(.
归档时间: |
|
查看次数: |
3447 次 |
最近记录: |