实体框架实体未显示相关实体的属性

时间:2010-12-15 09:29:37

标签: entity-framework

我是Entity Framework的新手。我使用Ninject在MVC中创建了一个多层应用程序 我在数据库中有三个表。说表A,表B和表C.

Table A has a foreign key relating it to Table B  
Table B has a foreign key relating it to Table C

Table A => Table B => Table C

我的应用程序有一个“服务”,将从MVC控制器调用 该服务充当每个实体(即TableAService,TableBService)的存储库,该实体负责从EF DataContext创建,读取,更新或删除实体,以及可能在这些实体上执行业务逻辑。

在我的MVC控制器中,我引用了相应的服务。例如:

private TableAService _tableAService;

public TableAController(EFDataContext dataContext)
{
    _tableAService = new TableAService(dataContext);
}

public ActionResult Index()
{
    return View();
}

TableAService看起来像这样:

private EFDataContext _dataContext;

public TableAService(EFDataContext dataContext)
{
    _dataContext = dataContext;
}

public TableA GetById(int tableAId)
{
    _dataContext.TableA.SingleOrDefault(ta => ta.TableAId == tableAId);
}

我很欣赏该示例的服务将与dataSource紧密耦合,我的实际实现略有不同但概念是相同的,我有一个带有dataContext的服务,我想从中返回实体。

问题: - 当我在TableAService中的GetById方法时,SingleOrDefault为我提供了一个TableB导航属性,它允许我访问所有TableB的属性,包括TableC导航属性。

但是,当我将TableA传递回Controller时,我无法访问任何TableB的属性。

在服务范围内,我也尝试过:

private ObjectSet<TableA> _objSet = _dataContext.CreateObjectSet<TableA>();

return _objSet.SingleOrDefault(ta => ta.TableAId == tableAId);

从TableA实体访问TableB上的TableC导航属性似乎没有任何区别。

非常感谢任何帮助!

干杯,

詹姆斯

3 个答案:

答案 0 :(得分:3)

导航属性的内容只能在活动的ObjectContext范围内加载。

这是必需的,因为实际行将通过往返数据库获取 在您的情况下,您尝试访问导航属性后,用于检索首先实体的ObjectContext已被丢弃并且连接丢失。

假设您正在使用Entity Framework 4,则有两个解决此问题的方法:

  • 热切加载:相关实体预先加载,即您明确指示实体框架在检索查询结果时加载所有相关实体。
    这可以完成以两种不同的方式:通过在查询的投影中包含相关实体,通过调用ObjectQuery.Include方法或在导航属性上调用Load方法,或者ObjectContext.LoadProperty方法。
  • 延迟加载:按需加载相关实体,即第一次访问导航属性的getter时。请注意,这仍然必须在ObjectContext的范围内完成。

在您的情况下,使用Include方法进行预先加载可能是最合适的解决方案:

public TableA GetById(int tableAId)
{
    return _dataContext.TableA
        .Include("TableB.TableC") // use dot-notation to specify depth in the object graph
        .SingleOrDefault(ta => ta.TableAId == tableAId);
}

相关资源:

答案 1 :(得分:2)

尝试将GetById方法更改为:

public TableA GetById(int tableAId)
{
    return _dataContext.TableA.Include("TableB").SingleOrDefault(ta => ta.TableAId == tableAId);
}

如果您想获取TableC记录,请使用:

public TableA GetById(int tableAId)
{
    return _dataContext.TableA.Include("TableB.TableC").SingleOrDefault(ta => ta.TableAId == tableAId);
}

原因是实体框架使用“延迟加载”,这意味着在您真正需要之前,不会从数据库加载内容。问题是,一旦您退出服务,数据上下文就不再存在以获取表B记录。 Include方法指示EF立即从相关表中加载数据。

答案 2 :(得分:0)

这需要一些挖掘,但我遇到的问题是我的应用程序没有引用System.Data.Entity。

添加对应用程序的引用允许我从控制器中访问相关对象的属性。

感谢您的回答,他们确实帮助我排除了可能性。我各投了一票。