考虑以下事件:我的项目中有一个代码第一个模型,其中包含Poco对象Animal。动物行有50个属性,我只想在我的应用程序中有5个属性。所以我将尝试将5个属性投影到像这样的Poco对象
List<Animal> animals = (from an in dbContext.Animal
where an.IsMammal
select new Animal { Id = an.Id , Color = an.Color , Height = an.Height, Width = an.Width , Hair = an.Hair }).ToList();
不适用于Animal是一个StrongTyped对象,无法转换为sql。
然而,如果我宣布一个新的Poco,那么与Animal说的AnimalDTO
完全相同List<AnimalDTO> animals = (from an in dbContext.Animal
where an.IsMammal
select new AnimalDTO { Id = an.Id , Color = an.Color , Height = an.Height, Width = an.Width , Hair = an.Hair }).ToList();
据我所知,就实体框架而言,Animal是一个映射类。我想要理解的是内部工作使一个案例成为有效选项而第二个案例不是。为什么.Net不允许使用Poco对象本质上是什么?有没有理由或者只是缺少一个功能?是否有任何解决方法可以使用第一个语句,以便我可以避免制作数百个基本相同的dtos?
答案 0 :(得分:1)
我找不到解释EF限制的任何链接。目前的EF(6)源也不太通信。如果抛出异常,它只会说
//不支持名义类型
所以我一直在思考它。
我认为最重要的是你可以把它弄得一团糟。更正式声明:您可以创建EF不会认为处于有效状态的实体对象。假设您的Animal
引用了Zoo
和ZooId
属性。您可以将动物园A放在Id中的动物园B的引用和id值中。
然后有跟踪实体。当你这样做
dbContext.Animal.ToList()
Animal
对象由EF本身实现。它们被添加到上下文的缓存和更改跟踪器中。如果你能够直接投射到实体对象中,那么它们不会被跟踪就可能不够明显。
假设你要给所有的mamals颜色相同。这看起来很明显:
var animals = (from an in dbContext.Animal
where an.IsMammal
select new Animal { Id = an.Id , Color = myColorVariable, .... });
dbContext.SaveChanges();
但你不能。 EF只想跟踪它已实现的实体,以便它可以信任它们处于有效状态。
顺便说一下,如果在投影前放置 .AsEnumerable()
,就可以做你想做的事。在AsEnumerable
EF失控后。同样,您可以使用由EF实现的有效Animal
对象,并为其分配一个不匹配的Zoo
对象和ZooId
。当EF再次获得控制权时会出现问题,例如当您尝试保存更改时。