为什么我不能在EF4.1中先用同样的poco代码来投射我的数据?[英] Why can I not use the same poco in code first in EF4.1 to project my data?

本文是小编为大家收集整理的关于为什么我不能在EF4.1中先用同样的poco代码来投射我的数据?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

考虑以下senario:我的项目中有一个代码与Poco Object 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();

不为动物工作是一个强壮的物体,不能转换为SQL.

,如果我声明新的poco,与动物完全相同,一个人说动物

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

我知道,就实体框架而言,动物的这种情况是映射的类.我想了解的是内部工作,使一种情况成为有效的选择,而第二个情况则不是.为什么.NET不允许使用POCO对象本质上是什么?是否有原因或仅仅是缺少功能?是否有任何解决方法可以使用第一个陈述,以便我可以避免制作数百个基本相同的DTO?

推荐答案

我找不到解释EF限制的任何链接.当前的EF(6)源也不是太交流.在抛出例外的情况下,它只说

//不支持名义类型

所以我一直在思考它一段时间.

我认为最重要的是您可以真正弄乱它.更正式说明:您可以创建EF不认为是有效状态的实体对象.假设您的Animal有一个对Zoo的引用,也有ZooId属性.您可以将Zoo A放入Zoo 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() 放置,则可以做自己想做的事情. AsEnumerable ef失控之后.同样,您可以将有效的Animal对象(由EF实现),并为其分配一个非匹配Zoo对象.当EF再次获得控制时,问题将出现,例如当您尝试保存更改时.

本文地址:https://www.itbaoku.cn/post/1557162.html

问题描述

Consider the following senario: I have a code first model in my project with the Poco object Animal. The animal row has 50 properties and I only want 5 of them in my application. So I will try to project the 5 properties to a Poco object like this

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

Is not working for Animal is a StrongTyped object and cannot be converted to sql.

Whereas if I declare a new Poco, exactly the same as the Animal one say 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();

I understand that this happens for Animal is a mapped class as far as Entity Framework is concerned. What I want to understand are the inner workings making the one case a valid option and the second one not. Why does .Net not allow the usage of the Poco object as what it essentially is? Is there a reason for that or is it just a feature missing? Is there any workaround to use the first statement so that I can avoid making hundreds of essentially identical dtos?

推荐答案

I can't find any link where this limitation of EF is explained. The current EF (6) source is not too communicative either. Where the exception is thrown it only says

// nominal types are not supported

So I've been pondering about it for a while.

I think the bottom line is you can make a real mess of it. More formally stated: you can create entity objects that EF would not consider to be in a valid state. Suppose your Animal had a reference to a Zoo and also a ZooId property. You could put zoo A in the reference and id value of zoo B in the Id.

Then there is the point of tracking entities. When you do

dbContext.Animal.ToList()

the Animal objects are materialized by EF itself. They are added to the context's cache and the change tracker. If you were able to project into entity objects directly, maybe it wouldn't be obvious enough that they don't get tracked.

Suppose you were to give all your mamals the same color. It might look obvious to do:

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

But you can't. EF only wants to track entities it has materialized itself so it can trust they are in a valid state.

By the way, you can do what you want if you put .AsEnumerable() right before you make a projection. After AsEnumerable EF is out of control. Similarly you could take a valid Animal object, materialized by EF, and assign a non-matching Zoo object and ZooId to it. The problems will come when EF gains control again, e.g. when you try to save changes.