为什么我的 Entity Framework Code First 代理集合为 null,为什么我不能设置它? [英] Why is my Entity Framework Code First proxy collection null and why can't I set it?

查看:43
本文介绍了为什么我的 Entity Framework Code First 代理集合为 null,为什么我不能设置它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 DBContext 并且有两个类,它们的属性都是虚拟的.我可以在调试器中看到,当我查询上下文时,我正在获取一个代理对象.但是,当我尝试添加时,集合属性仍然为空.我认为代理会确保集合被初始化.

I am using DBContext and have two classes whose properties are all virtual. I can see in the debugger that I am getting a proxy object when I query the context. However, a collection property is still null when I try to add to it. I thought that the proxy would ensure that collection is initialized.

因为我的 Poco 对象可以在其数据上下文之外使用,所以我在构造函数中添加了对集合为 null 的检查,并在必要时创建它:

Because my Poco object can be used outside of its data context, I added a check for the collection being null in the constructor and create it if necessary:

public class DanceStyle
{
    public DanceStyle()
    {
        if (DanceEvents == null)
        {
            DanceEvents = new Collection<DanceEvent>();
        }
    }
    ...
    public virtual ICollection<DanceEvent> DanceEvents { get; set; }
}

这在数据上下文之外工作,但如果我使用查询检索对象,尽管测试为真,但当我尝试设置它时,我得到以下异常:'DanceStyle_B6089AE40D178593955F1328A70EAA3D8F0F01DDE95A9F01DDE959F01DDE95F90F01DDE95A9F01DDE959F90F01DDE95A90F01DDE959F90F01DDE959F901DDE959F9001DDE959F9001DDE95F9001DDE959F9001设置,因为该集合已设置为 EntityCollection.'

That works outside the data context but if I retrieve an object using a query, although the test is true, when I try to set it, I get following exception: 'The property 'DanceEvents' on type 'DanceStyle_B6089AE40D178593955F1328A70EAA3D8F0F01DDE9F9FBD615F60A34F9178B94' cannot be set because the collection is already set to an EntityCollection.'

我可以看到它是空的,我不能添加它,但我也不能将它设置为一个集合,因为代理说它已经设置了.因此不能使用.我很困惑.

I can see it is null and I cannot add to it, but neither can I set it to a collection because the proxy says it is already set. Therefore I cannot use it. I'm confused.

这是 DanceEvent 类:

Here is the DanceEvent class:

public class DanceEvent
{
    public DanceEvent()
    {
        if (DanceStyles == null)
        {
            DanceStyles = new Collection<DanceStyle>();
        }
    }
    ...
    public virtual ICollection<DanceStyle> DanceStyles { get; set; }
}

我在上面的代码中省略了其他值类型属性.对于上下文类中的这些类,我没有其他映射.

I have omitted the other value-type properties from the code above. I have no other mappings for those classes in the context class.

推荐答案

我在这里找到了这个问题的解决方案:代码优先添加到集合?如何在存储库中使用 Code First?

I found the solution to this problem here: Code First adding to collections? How to use Code First with repositories?

我从除集合和延迟加载对象之外的所有属性(即所有本机类型)中删除了虚拟".

I removed 'virtual' from all properties except collections and lazy loaded objects, that is, all native types.

但我仍然不明白你怎么会遇到这样的情况:你有一个不能使用的空集合,也无法将它设置为有效的集合.

But I still don't understand how you can end up with the situation where you have a null collection that you cannot use and have no way to set it to a valid collection.

我还发现了 这个答案来自MSDN 论坛上的 Rowan Miller

如果您将所有属性设为虚拟,那么 EF 将在运行时生成从您的 POCO 类派生的代理类,这些代理允许 EF 实时了解更改,而不必捕获对象的原始值,然后保存时扫描更改(这显然具有性能和内存使用优势,但除非您将大量实体加载到内存中,否则差异可以忽略不计).这些被称为更改跟踪代理",如果您将导航属性设为虚拟,则仍会生成代理,但它会简单得多,并且仅包含一些在您访问导航属性时执行延迟加载的逻辑.

If you make all your properties virtual then EF will generate proxy classes at runtime that derives from your POCO classed, these proxies allow EF to find out about changes in real time rather than having to capture the original values of your object and then scan for changes when you save (this is obviously has performance and memory usage benefits but the difference will be negligible unless you have a large number of entities loaded into memory). These are known as 'change tracking proxies', if you make your navigation properties virtual then a proxy is still generated but it is much simpler and just includes some logic to perform lazy loading when you access a navigation property.

由于您的原始代码正在生成更改跟踪代理,因此 EF 将您的集合属性替换为特殊的集合类型,以帮助它了解更改.因为您尝试将集合设置回构造函数中的一个简单列表,所以您会收到异常.

Because your original code was generating change tracking proxies, EF was replacing your collection property with a special collection type to help it find out about changes. Because you try and set the collection back to a simple list in the constructor you are getting the exception.

除非您看到性能问题,否则我会遵循 Terrence 的建议,并从您的非导航属性中删除虚拟".

Unless you are seeing performance issues I would follow Terrence's suggestion and just remove 'virtual' from your non-navigation properties.

~罗文

因此,如果我的所有属性都是虚拟的,那么我似乎只有完整的更改跟踪代理"问题.但既然如此,为什么我仍然不能在更改跟踪代理上使用虚拟属性?这段代码在第三行炸毁了,因为 ds2.DanceEvents 是 null 并且不能在构造函数中设置:

So it appears that I only have the problem with a full 'change tracking proxy' if all my properties are virtual. But given that, why can I still not use the virtual property on the change tracking proxy? This code blows up on line three because ds2.DanceEvents is null and cannot be set in the constructor:

DanceStyle ds2 = ctx.DanceStyles.Where(ds => ds.DanceStyleId == 1).Single();
DanceEvent evt = CreateDanceEvent();
ds2.DanceEvents.Add(evt);

我仍然很困惑,尽管我的代码由于上面的修复而现在可以工作了.

I'm still confused, even though my code is now working because of the fix above.

这篇关于为什么我的 Entity Framework Code First 代理集合为 null,为什么我不能设置它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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