我在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()
使其工作,但会产生性能问题。
1条答案
按热度按时间ruyhziif1#
所有的LINQ代码都使用相同的语法,所以所有的LINQ代码在编译时通过或失败都是一样的。取决于使用的LINQ提供程序。如果使用EF,则使用LINQ to Entities提供程序。该提供程序必须能够将LINQ代码转换为SQL代码,以便对数据库执行。希望您能理解为什么使用反射的代码不能转换为SQL。通过调用
ToList
,您可以计算LINQ to Entities查询并获得一个本地集合,因此后续的FirstOrDefault
调用使用LINQ to Objects提供程序。它不需要转换任何内容,所以反射是可以的。基本上,你需要摆脱反射。你需要使用特定的类型和成员:
我怀疑这里的问题是您的代码在泛型存储库中,而
MainEntity
是泛型类型参数,而不是具体的类型。解决方法是定义一个带有Id
属性的接口,然后让所有实体实现该接口。然后,您可以将泛型类型约束添加到存储库类中的该参数,这样MainEntity.Id
就有效了。话虽如此,如果我关于这段代码在仓库中的说法是正确的,那么你从一开始就错了。你不应该在使用EF时自己实现Repository模式。EF上下文是一个工作单元,每个
DbSet
都已经是一个仓库了,所以你只是在给自己制造问题。