c# - 具有泛型类属性的 LINQ 表达式

标签 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)));
}

不幸的是我遇到了异常:

LINQ to Entities does not recognize the method 'System.Object GetValue(System.Object)' method, and this method cannot be translated into a store expression.

最佳答案

异常是正常的,因为通过反射获取属性显然无法转换为 SQL。

我会尝试的一件事是创建一个公开 Id 的通用接口(interface)给定类型的属性:

public interface HasId<T> {
    T Id { get; set; }
}

现在您可以声明您的实体实现了 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));
}

注意添加的通用限制:where T : class, HasId<TId> .这使您能够编写简化的 j.Id ,它返回一个 TId值(value),而不是诉诸反射(reflection)。

请注意,我还没有运行或测试过这段代码;这只是我看到您的问题时的一个想法,希望对您有所帮助。

更新:

这是另一种可能的解决方案,它不需要您以任何方式声明接口(interface)或更改您的类:

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

我在这里所做的是添加 Expression<Func<T, TId>> idSelector参数,一个可以返回 Id 的表达式T 的给定实例.

您可以这样调用该方法:

var modified = GetModified(dbObjects, yourIdArray, entity => entity.Id);

(只有第三个参数是新的;保持其他参数不变)。

同样,我还没有测试它是否有效甚至编译,因为我这里没有装有 VS 的计算机:(。

关于c# - 具有泛型类属性的 LINQ 表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18930503/

相关文章:

c# - 如何使具有 List<> 成员的类不可变?

c# - 比较两个 DLL

c# - 在 Entity Framework 中加入多个实体,2 个 DbSet 和一个列表

c# - 'DES' 类和 'DESCryptoServiceProvider' 类有什么区别?

c# - 如何根据 Dictionary int 值订购 Dictionary<int, string> 列表?

c# - 将泛型函数作为 Linq 表达式 C# 传递

c# - 我如何将此linq代码转换为嵌入式SQL

java - 如何返回我明确作为参数传递的类型?

c# - 通用 ToSelectListItem 方法

java - 确定通用类型字段的类类型