从db

时间:2017-12-03 12:15:03

标签: c# entity-framework asp.net-web-api entity-framework-6

我正在使用EF 6.X的Code First方法。 有两个实体和一个上下文:

class Product
{
   long Id { get; set; }
   string Name { get; set; }
   ProductCategory ProductCategory { get; set; }
}

class ProductCategory
{
   long Id { get; set; }
   string Name { get; set; }
}

class ProductContext : DbContext
{
    public DbSet<Product> Products { get; set; }
    public DbSet<ProductCategory> ProductCategories { get; set; }
}

当我使用预期的命名约定时,我能够从模型创建数据库,添加项目并将其读回 - 无需数据注释,也无需使用流畅的API。 实际上,我确实使用了流畅的API在某些属性上设置HasMaxLength,但该配置代码没有设置密钥或外键。

重要的一点是,在调用以下内容时:

Product product = context.Products.Find(1).FirstOrDefault();

产品的ProductCategory使用ProductCategory实例正确填充。 我遇到的问题是这种行为似乎不一致。

在WebApi控制器中,我创建了一个ProductContext类的实例,并且读取执行与上面代码片段相同的操作。 结果是正确实例化的Product,但其ProductCategory属性设置为null。

任何人都可以解释这两种用法之间的差异吗?我的DbContext派生上下文能够将Product表中的外键条目转换为ProductCategory类的实例的先决条件是什么?

1 个答案:

答案 0 :(得分:1)

默认情况下,实体框架在从DB加载对象时不会加载相关对象。你必须:

使用Include声明:

context.Products.Include(p => p.ProductCategory).FirstOrDefault(p => p.Id == 1);

或者通过将导航属性标记为virtual来使用延迟加载:

class Product
{
   long Id { get; set; }
   string Name { get; set; }
   virtual ProductCategory ProductCategory { get; set; }
}

然后在您第一次触摸时加载ProductCategory

或手动加载参考:

context.Entry(product).Reference(p => p.ProductCategory).Load();