使用泛型时,无法转换Linq表达式

8xiog9wr  于 2022-12-06  发布在  其他
关注(0)|答案(1)|浏览(199)

我在C#代码中使用泛型

var _Entity = context.Set<T>()
                 .FirstOrDefault(r => (long)r.GetType().GetProperty("Id").GetValue(r, null) == Id);

此代码行引发异常

(long)r.GetType().GetProperty("Id").GetValue(r, null)

如果我删除上面的线,它将工作绝对罚款。

异常消息LINQ表达式'DbSet\r\n .其中(f =〉(长整型)f.获取类型().获取属性(“Id”).获取值(\r\n对象:f,\r\n索引:null)== __model_Id_0)'无法转换。请以可转换的形式重写查询,或者通过插入对AsEnumerable()、AsAsAsyncEnumerable()、ToList()或ToListAsync()的调用来显式切换到客户端计算。有关详细信息,请参阅https://go.microsoft.com/fwlink/?linkid=2101038

在语句中添加.ToList()还有一件事

context.Set<T>().ToList()

使其工作,但会产生性能问题。

ruyhziif

ruyhziif1#

所有的LINQ代码都使用相同的语法,所以所有的LINQ代码在编译时通过或失败都是一样的。取决于使用的LINQ提供程序。如果使用EF,则使用LINQ to Entities提供程序。该提供程序必须能够将LINQ代码转换为SQL代码,以便对数据库执行。希望您能理解为什么使用反射的代码不能转换为SQL。通过调用ToList,您可以计算LINQ to Entities查询并获得一个本地集合,因此后续的FirstOrDefault调用使用LINQ to Objects提供程序。它不需要转换任何内容,所以反射是可以的。
基本上,你需要摆脱反射。你需要使用特定的类型和成员:

var _Entity = context.Set<MainEntity>().FirstOrDefault(r => r.Id == Id);

我怀疑这里的问题是您的代码在泛型存储库中,而MainEntity是泛型类型参数,而不是具体的类型。解决方法是定义一个带有Id属性的接口,然后让所有实体实现该接口。然后,您可以将泛型类型约束添加到存储库类中的该参数,这样MainEntity.Id就有效了。
话虽如此,如果我关于这段代码在仓库中的说法是正确的,那么你从一开始就错了。你不应该在使用EF时自己实现Repository模式。EF上下文是一个工作单元,每个DbSet都已经是一个仓库了,所以你只是在给自己制造问题。

相关问题