实体框架:我设置的外键,调用SaveChanges然后访问导航属性,但它不会加载相关实体。 为什

2019-07-22 09:44发布

我使用实体框架5码首先这个实体类:

public class Survey
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }

    public string SurveyName { get; set; }

    [Required]
    public int ClientID { get; set; }

    [ForeignKey("ClientID")]
    public virtual Client Client { get; set; }
}

而在我的控制器的创建方法我这样做:

    Survey entity = new Survey()
    {
        SurveyName = "Test Name",
        ClientID = 4
    };
    db.Surveys.Add(entity);
    db.SaveChanges();
    Client c1 = entity.Client;                    //Why is this null?
    Client c2 = db.Clients.Find(entity.ClientID); //But this isn't?

    string s2 = c2.ClientName;
    string s1 = c1.ClientName;   //null reference thrown here

客户端的导航属性保持的SaveChanges后空。 我期待的调用,因为外键的存在是为了从数据库中加载客户端。 它为什么这样做呢?

编辑代码在这里来自当我的控制器都依赖DbContext 。 我得到这个工作,我不久后重新分解使用存储库和工作单位的代码。 这一举动的一部分的事实,它只是感觉不对使用驱动Create时,我想用new 。 发生了什么事,然后是我打一个问题是如何确保代理使用存储库模式时创建 。

Answer 1:

为了确保导航属性的懒加载一定会给你所创建的父母,你不能创建后Surveynew运营商,但通过上下文实例的方式创建它,因为它会实例化一个动态代理,它能够懒洋洋地加载相关的Client 。 这就是什么DbSet<T>.Create()方法用于:

Survey entity = db.Surveys.Create();

entity.SurveyName = "Test Name";
entity.ClientID = 4;

db.Surveys.Add(entity);
db.SaveChanges();

Client c1 = entity.Client;
string s1 = c1.ClientName;
// will work now if a Client with ID 4 exists in the DB

只是强调:这不是行entity.ClientID = 4;db.Surveys.Add(entity);db.SaveChanges加载从DB客户端,但该线Client c1 = entity.Client; (延迟加载)。



Answer 2:

就像@NicholasButler说,打电话SaveChanges做什么它在锡说-你可以看到这一点,如果您调试代码:对智能跟踪输出将显示它已用于插入生成的SQL /更新你坚持,但不会有后续选择。

请记住,除非你是预先加载(使用Include法),相关实体不加载进行检索时,所以按理说,创建/更新他们将不会。

实体框架(从我认为4.1及以上版本),支持延迟加载。 这意味着,如果它的启用,这样的代码Client c1 = entity.Client; 应该加载该Client对象。 需要明确的是,这种操作不直接相关SaveChanges调用。

它将支付检查是否db.Configuration.LazyLoadingEnabled设置为true 。 如果没有,尝试将其设定为true ,看看Client c1 = entity.Client; 仍然是零。

总之,调用SaveChanges不会触发负荷,但如果启用了延迟加载,访问entity.Client如果它尚未加载应触发实体的负荷。

编辑:

我应该尽管这个较早,但你不会你上越来越懒加载Survey entity对象。 其原因是,EF通过创建从一个派生的类,但覆盖标记为属性的工作延迟加载魔virtual支持延迟加载。 为此,它会在您执行检索,所以你的entity对象将不会延迟加载任何东西,因为它主张。

试试这只是您的来电后SaveChanges

Survey entity2 = db.Surveys.Find(entity.ID);
Client c1 = entity2.Client;

这应该表现出你是以后的行为。



Answer 3:

您需要定义上的所有属性Survey类虚拟,使延迟加载。

见http://msdn.microsoft.com/en-us/library/vstudio/dd468057(v=vs.100).aspx以获取更多信息。



Answer 4:

我期待的调用,因为外键的存在是为了从数据库中加载客户端。 它为什么这样做呢?

它没有这样做,因为你还没有要求它。 调用后SaveChanges() ,EF没有引用的行中的数据,它不会让一个潜在的冗余数据库调用得到它。

调用db.Clients.Find(...告诉EF去从数据库中,这就是为什么它返回对象读取该行。



文章来源: Entity Framework: I set the foreign key, SaveChanges then access the navigation property, but it doesn't load the related entity. Why not?