1

我一直在使用 Entity Framework 开发 ASP.NET C#,有些人在某些关键点上帮助了我很多。

还有一点我不能完全理解。当我们从 EF 检索数据时,我们不应该使用对象及其子对象(外键关系表数据)吗?

这是我的数据库设计(也显示在我之前回答的问题中) 在此处输入图像描述

在我的代码中,我简单地得到如下的成员实体:

//In some aspx.cs file
var Mem = new MemberManager().GetById(2);

//In MemberManager class
public Member GetById(long id)
        {
            using(var Context = new NoxonEntities())
            {
                return Context.Member.First(c => c.Id == id);
            }
        }

当我这样做时:

var Mem = new MemberManager().GetById(2);
var Lang = Mem.Language;
//I get 
//Error: 'Mem.Language' threw an exception of type 'System.ObjectDisposedException'

为了摆脱这个异常,我需要这样做:

public Member GetById(long id)
        {
            using(var Context = new NoxonEntities())
            {
                var Result = Context.Member.First(c => c.Id == id);
                //Getting the Language Entity
                Result.Language = Context.Language.First(c => c.Id == Result.LanguageId);

                return Result;
            }
        }

我是否必须运行 SELECT 才能拥有完整的实体?如果有另一个与语言表相关的表,比如说功能表。我应该这样做:

public Member GetById(long id)
            {
                using(var Context = new NoxonEntities())
                {
                    var Result = Context.Member.First(c => c.Id == id);
                    //Getting the Language Entity
                    Result.Language = Context.Language.First(c => c.Id == Result.LanguageId);
                    Result.Language.Feature = Context.Language.Feature.First(c => c.Id == Result.FeatureId);
                    return Result;
                }
            }

这可能会持续很长时间,我很确定(至少我真的希望)我错了,但是如果我们在选择之后不能使用对象及其子对象,那么拥有 EF 的目的是什么?我们可以只使用using(var Context = new NoxonEntities())块中的子对象吗?

谢谢,

4

2 回答 2

3

将上下文视为数据库连接。当您在using语句中创建上下文并在using. 该块之后的所有内容都using无法再访问数据库连接。你在这里得到一个例外......

var Lang = Mem.Language;

...因为延迟加载尝试Language从数据库加载导航属性,但与数据库的连接已被释放。当与数据库的连接仍然可用时,您只能在块内使用这种延迟加载。using

您可以通过使用预先加载来简化示例中导航属性的加载Include

public Member GetById(long id)
{
    using(var Context = new NoxonEntities())
    {
        return Context.Member.Include("Language").First(c => c.Id == id);
    }
}

或者对于两个导航属性都使用:

return Context.Member.Include("Language.Feature").First(c => c.Id == id);

它将在一个数据库查询中加载成员、语言和功能。

于 2012-09-13T11:15:18.327 回答
2

您的问题是由于延迟加载造成的。发生的事情是 EF 没有加载您的相关实体Language,因为它不确定它是否需要数据。然后,您正在处理上下文,因此当您尝试访问Language导航属性时,它无法进行跳转。

您在这里有几个选择。你可以预先加载,这里有一篇关于预先加载的很棒的博客文章,语言实体:

var Result = Context.Member.Include("Language").First(c => c.Id == id);

或者,您需要在整个请求期间保持上下文处于活动状态。这是一篇关于为每个请求保持上下文活跃的好方法的好帖子

我确实记得你是另一个帖子 - 我相信你正在分离你的实体并将其存储在其他地方,然后重新附加。如果这与该功能有关,那么在将语言对象重新附加到上下文访问它也将解决您的问题。

于 2012-09-13T11:17:55.857 回答