0

考虑以下情景:我的项目中有一个带有 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 对象的本质?这是有原因的还是只是缺少一个功能?是否有任何解决方法可以使用第一条语句,这样我就可以避免制作数百个基本相同的 dto?

4

1 回答 1

1

我找不到任何解释 EF 限制的链接。当前的 EF (6) 源也不太具有交流性。抛出异常的地方只说

// 不支持名义类型

所以我一直在思考这个问题。

我认为底线是你可以把它弄得一团糟。更正式地说:您可以创建 EF 不会认为处于有效状态的实体对象。假设您Animal引用了 aZooZooId属性。您可以将动物园 A 放在 Id 中动物园 B 的参考和 id 值中。

然后是跟踪实体的重点。当你这样做

dbContext.Animal.ToList()

Animal对象由 EF 本身实现。它们被添加到上下文的缓存和更改跟踪器中。如果您能够直接投影到实体对象中,那么它们不会被跟踪可能不够明显。

假设你要给所有的哺乳动物相同的颜色。这样做看起来很明显:

    var animals = (from an in dbContext.Animal 
        where an.IsMammal
        select new Animal { Id = an.Id , Color = myColorVariable, .... });
    dbContext.SaveChanges();

但你不能。EF 只想跟踪它自己实现的实体,以便它可以相信它们处于有效状态。

顺便说一句,如果你.AsEnumerable()在做投影之前就做好了,你就可以做你想做的事。AsEnumerableEF失控后。同样,您可以获取一个Animal由 EF 实现的有效对象,并为其分配一个不匹配的Zoo对象ZooId。当 EF 再次获得控制权时,问题就会出现,例如,当您尝试保存更改时。

于 2013-05-03T12:39:05.843 回答