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

查看:62
本文介绍了为什么我不能先在EF4.1的代码中使用相同的poco来投影数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下问题:我的项目中有一个带有Poco对象Animal的代码优先模型.动物行有50个属性,而我的应用程序中只需要5个属性.因此,我将尝试将5个属性投影到这样的Poco对象上

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

不适用于Animal是StrongTyped对象,无法转换为sql.

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

如果我声明一个新的Poco,就像动物说的是AnimalDTO一样

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

据我了解,就实体框架而言,这是因为Animal是一个映射的类.我想了解的是内部工作原理,使一种情况成为有效选择,而第二种则不是.为什么.Net不允许使用Poco对象,因为它本质上是什么?是有原因还是只是缺少功能?有没有使用第一条语句的解决方法,这样我就可以避免制作数百个实质上相同的dto?

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?

推荐答案

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

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.

我认为最重要的是,您可以将其弄得一团糟.更正式地说:您可以创建EF不会认为其处于有效状态的实体对象.假设您的Animal引用了ZooZooId属性.您可以将动物园A的引用和ID值输入动物园B的ID.

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

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

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

但是你不能. EF只想跟踪自己已实现的实体,因此它可以信任它们处于有效状态.

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

顺便说一句,如果在进行投影之前放下 .AsEnumerable() ,则可以执行所需的操作.在AsEnumerable之后,EF失控.同样,您可以获取一个由EF实现的有效Animal对象,并为其分配一个不匹配的Zoo对象和ZooId.当EF再次获得控制权时(例如,当您尝试保存更改时.

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.

这篇关于为什么我不能先在EF4.1的代码中使用相同的poco来投影数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆