为什么简单的实体数据模型关系返回null而不是对象的引用?

时间:2009-02-16 00:38:28

标签: .net entity-framework

我有两个简单的表和SQL Server Express中定义的外键:


产品

  • ProductID [auto-inc]
  • 名称
  • CompanyID [not-null]

公司

  • CompanyID [auto-inc]
  • 名称

FK_Product_Company

  • Product.CompanyID = Company.CompanyID

我创建了一个ADO.NET实体数据模型并将所有表添加到其中。 .edmx文件显示设计器中的1对多关系。我用数据手动填充数据库,以确保每个产品都有公司。但是,每当我尝试访问产品的公司时,它总是返回null而不是公司的实例。

例如,在C#中运行以下代码,返回null:

var _db = new MyDBEntities();
var product = (from p in _db.Product
               where p.ProductID == 3
               select p).First();
product.Company // == null

我是否缺少任何可以让它发挥作用的步骤?

由于


我尝试过的事情:


运行以下SQL,正确返回公司记录。

SELECT Company.*
FROM Product
  LEFT JOIN Company ON (Product.CompanyID = Company.CompanyID)
WHERE Product.ProductID = 3

我要调试此问题的下一步是运行以下代码:

var _db = new MyDBEntities();
var product = (from p in _db.Product
               where p.ProductID == 3
               select p).First();
var company = (from c in _db.Company
               where c.CompanyID == product.CompanyID
               select c).First();

但是,这不能编译,因为ORM生成器隐藏了Product.CompanyID字段,我在设计器中看不到添加它的选项。


下一个最好的运行方法我想是以下内容,它确实返回了一家公司:

var _db = new MyDBEntities();
var company = (from c in _db.Company
               where c.CompanyID == 2
               select c).First();

为了清楚起见,ID为3的产品对应ID为2的公司。


我尝试使用 LINQ to SQL Classes 创建完全相同的关系,它运行正常。

当然,我没有使用DB Entities类,而是使用Data Context类。

4 个答案:

答案 0 :(得分:11)

您需要将.Include方法添加到查询中。

var _db = new MyDBEntities();
var product = (from p in _db.Product.Include("Company")
               where p.ProductID == 3
               select p).First();

答案 1 :(得分:6)

实体框架支持深度加载,但延迟加载不是(实体框架2.0中将支持延迟加载)。

使用Load()或.Include(“Company”),就像以前的帖子一样,它会起作用。

以下是如何使实体框架变得懒惰: http://blogs.msdn.com/jkowalski/archive/2008/05/12/transparent-lazy-loading-for-entity-framework-part-1.aspx

答案 2 :(得分:1)

您可以按照上面的建议使用Include。

或者尝试拨打

product.Company.Load()来检索对象。

实体框架使用延迟加载来避免在实际需要对象之前进行不必要的查询。

此处有关于延迟加载的更多信息:http://www.code-magazine.com/article.aspx?quickid=0711051&page=4

答案 3 :(得分:0)

使用“Include”需要字符串参数,这使得重构变得困难。更好的选择是在select子句中提及你的关系:

var product = (from p in _db.Product
     where p.ProductID == 3
     select new {p.Name, Company = p.Company.Name})

只要在LINQ表达式中提到“Product.Company”,EF编译器就会看到它并将加载所有提到的列。 额外的好处是生成的SQL将只包含您真正需要的列(更少的流量)

如果你需要读写你的对象,它就无法工作。