3

我经常使用该System.Data.Entity.DbExtensions Include()方法将复杂的实体字段包含在我的存储库的查询结果中。但是,当我将实体投影到新类中时,我似乎失去了包含的复杂实体字段的这种“具体化”。例如,假设我想Event从我的仓库中返回一个对象,并且能够访问复杂的实体字段Assessment

public class EventRepository {
...
    public IList<Event> GetEvents() {
        using (var context = new MyDatabaseContext()) {
            return context.Events
                .Include(evnt => evnt.ActualAssessment)
                .ToList();
        }
    }
...
}

然后我可以顺利运行以下代码,因为Include我在上面使用了:

var repoEvents = new EventRepository();
var events = repoEvents.GetEvents();
Console.WriteLine(events[0].ActualAssessment.AssessmentDate.ToString());

但是假设我现在想将 s 投影到带有一些额外信息Event的包装对象中,如下所示:ExtendedEvent

public class EventRepository {
...
    public IList<ExtendedEvent> GetExtendedEvents() {
        using (var context = new MyDatabaseContext()) {
            return context.Events
                .Include(evnt => evnt.ActualAssessment)
                .Select(evnt => new {
                    TheEvent = evnt,
                    SomeExtraData = 123
                })
                .ToList()
                .Select(evntInfo => {
                    return new ExtendedEvent {
                        TheEvent = evntInfo.TheEvent,
                        SomeExtraData = evntInfo.SomeExtraData
                    };
                })
                .ToList();
        }
    }
...
}

我现在尝试运行这段代码:

var repoEvents = new EventRepository();
var extendedEvents = repoEvents.GetExtendedEvents();
Console.WriteLine(extendedEvents[0].TheEvent.ActualAssessment.AssessmentDate.ToString());

这给了我错误“ObjectContext 实例已被释放,不能再用于需要连接的操作。” -ActualAssessment尽管我使用了 ,但它并没有被预先加载Include,显然是因为我将它投影到一个新的包装器对象中。我怎样才能使ActualAssessment被包括在内?

4

1 回答 1

4

是的,Include在预测中被忽略。您可以尝试将相关导航属性的一部分投影到匿名对象中:

public IList<ExtendedEvent> GetExtendedEvents() {
    using (var context = new MyDatabaseContext()) {
        return context.Events
            .Select(evnt => new {
                TheEvent = evnt,
                SomeExtraData = 123,
                ActualAssessment = evnt.ActualAssessment
            })
            .ToList()
            .Select(evntInfo => {
                return new ExtendedEvent {
                    TheEvent = evntInfo.TheEvent,
                    SomeExtraData = evntInfo.SomeExtraData
                };
            })
            .ToList();
    }
}

ActualAssessment附加到上下文中,TheEvent.ActualAssessment 如果出现自动关系修复将填充

  • 您没有禁用更改跟踪
  • 关系不是多对多的

作为旁注:您可以使用AsEnumerable()而不是第一个ToList()来避免创建匿名对象列表的不必要开销。

编辑

对于多对多关系或在禁用更改跟踪的情况下,您必须在数据库查询具体化后设置导航属性,例如:

            .Select(evntInfo => {
                evntInfo.TheEvent.ActualAssessment = evntInfo.ActualAssessment;
                return new ExtendedEvent {
                    TheEvent = evntInfo.TheEvent,
                    SomeExtraData = evntInfo.SomeExtraData
                };
            })
于 2012-10-30T16:28:55.993 回答