2

我遇到了第一次检查时似乎是 Entity Framework 5 中的错误。

我有一个 T4 生成的 DbContext 和实体类。注意,我稍微修改了默认的 T4 模板以支持可观察的集合。

延迟加载已启用并且在整个应用程序中运行良好,除非我这样做:

courseEnrolment.Student.CourseEnrolments.ToList()

也就是说,对于我已经加载到内存中的 courseEnrolment,我正在访问它的父 ( Student) 并加载CourseEnrolments与其关联的所有内容,其中还包括原始 courseEnrolment。发生这种情况时,第二个CourseEnrolment成功地延迟加载到 conext (和Local集合)中,但它的所有导航属性都是null而不是对应的DynamicProxy.

这是新加载的CourseEnrolment样子。请注意,尽管从数据库成功加载了正常属性,但所有导航属性均为空:

在此处输入图像描述

这就是正常的CourseEnrolment样子:

在此处输入图像描述

有谁知道为什么一个成功延迟加载的实体无法通过延迟加载来实现自己的导航属性?


更新有关问题来源的更多信息

我已经设法用以下最少的代码重新创建了这个问题。这个问题似乎与我观察Local收藏有关。

        var context = new PlannerEntities();

        Debug.Assert(context.CourseEnrolments.Local.Count() == 0);

        context.CourseEnrolments.Local.CollectionChanged += (sender, e) =>
        {
            Debug.Assert(e.NewItems.OfType<CourseEnrolment>().All(x => x.Adviser != null), "newly added entity has null navigatigon properties");
        };

        var c1 = context.CourseEnrolments.Single(x => x.EnrolmentId == "GA13108937");

        Debug.Assert(context.CourseEnrolments.Local.Count() == 1);
        Debug.Assert(context.CourseEnrolments.Local.All(x => x.Adviser != null));

        c1.Student.CourseEnrolments.ToList();

        Debug.Assert(context.CourseEnrolments.Local.Count() == 2);

        Debug.Assert(context.CourseEnrolments.Local.All(x => x.Adviser != null),"some navigation properties were not lazy loaded");

处理程序中的断言CollectionChanged失败,这表明此时导航属性未满足。最后的断言不会失败,这将在稍后的时间点表明,在ObservableCollection处理完事件之后,实体已完成。

任何想法我可以如何访问集合CollectionChanged事件的导航属性?Local

4

2 回答 2

1

直到调用 CollectionChanged 事件后才会创建延迟加载代理。使用 Dispatcher 会导致调用被放置在消息队列上并在稍后执行(之后多长时间不确定),因此在调用 Debug.Assert 之前会执行 CollectionChanged 事件并创建延迟加载代理。

但是,我强烈避免为此目的使用 Dispatcher,因为它是不确定的并且存在竞争条件的风险。

为了像在原始代码中一样使用 CollectionChanged 事件,您需要更改跟踪代理,而不仅仅是延迟加载代理。要让 Entity Framework 生成更改跟踪代理,您的所有属性,无论是集合、对象还是原始类型,都需要设置为 virtual

相关问题:https ://github.com/brockallen/BrockAllen.MembershipReboot/issues/290

于 2014-09-05T09:17:17.203 回答
0

好吧,我已经设法通过调度 Assert 调用来让它工作

context.CourseEnrolments.Local.CollectionChanged += (sender, e) =>
{
    Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>{
        Debug.Assert(e.NewItems.OfType<CourseEnrolment>().All(x => x.Adviser != null), "newly added entity has null navigation properties");
     }));
};

这是最好的解决方案吗?

于 2013-10-16T15:20:18.357 回答