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

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

在数据上下文之外可行,但是如果我使用查询检索对象,尽管测试为true,则在尝试设置它时,会出现以下异常:'DanceStyle_B6089AE40D178593955F1328A70EAA3D8F0F01DDE9F9FBDF160F60A34F9178B94'类型的'DanceEvents'属性设置,因为该集合已经设置为EntityCollection。'

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

这是DanceEvent类: 通用标签

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

有帮助吗?

解决方案 2

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

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

但是我仍然不明白如何解决无法使用null集合并且无法将其设置为有效集合的情况。

我还找到了此答案来自MSDN论坛上的Rowan Miller

嗨,

如果将所有属性虚拟化,则EF会在运行时生成从POCO分类派生的代理类,这些代理使EF可以实时发现有关更改的信息,而不必捕获对象的原始值,然后保存时扫描更改(这显然具有性能和内存使用方面的好处,但是除非您将大量实体加载到内存中,否则差异可以忽略不计)。这些被称为“变更跟踪代理”,如果您将导航属性设置为虚拟,则仍会生成代理,但是代理要简单得多,并且仅包含一些逻辑,以便在访问导航属性时执行延迟加载。

由于您的原始代码正在生成变更跟踪代理,因此EF用特殊的收集类型替换了您的收集属性,以帮助其查找更改。因为您尝试将集合设置回构造函数中的简单列表,所以您将获得异常。

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

〜罗恩

因此,如果我所有的属性都是虚拟的,那么似乎只有完整的“变更跟踪代理”才有问题。但是鉴于此,为什么我仍然不能在更改跟踪代理上使用虚拟属性?这段代码在第三行爆炸,因为ds2.DanceEvents为null且无法在构造函数中设置: 通用标签

尽管由于上述修复,我的代码现在可以正常工作,但我仍然感到困惑。

其他提示

正如您在自己的问题的答案中正确观察到的那样,通过防止实体框架创建更改跟踪代理,从集合属性中删除“虚拟”关键字可以解决该问题。但是,对于许多人来说,这并不是一个解决方案,因为更改跟踪代理确实非常方便,并且可以帮助您避免忘记在代码中正确的位置检测更改的情况。

更好的方法是修改POCO类,以便它们在其get访问器而不是构造函数中实例化集合属性。这是您的POCO类,已修改为允许创建更改跟踪代理: 通用标签

在上面的代码中,collection属性不再是自动的,而是具有一个后备字段。最好保留对setter的保护,以防止任何代码(代理以外的代码)随后修改这些属性。您会注意到该构造函数不再是必需的,并且已被删除。

老问题...

Poco课程: 通用标签

和代理代码: 通用标签

如您所见,ExtityFramework 5的代理类中引发了异常。这意味着行为仍然存在。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top