1

我首先使用代码编写使用 WebAPI 2.0 和 EF6.0 的 API。所以它必然是一个断开连接的 dbcontext 场景。

我的域名如下

public class Patient
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email ( get; set; }
    public virtual Nutritionist Nutritionist { get; set; }
}

public class Nutritionist
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual List<Patient> Patients { get; set; }
}

如果患者对当前的营养师不满意,用户界面将允许患者选择其他营养师。所以我的 API 需要支持这一点。我认为这将是对患者的简单更新。但以下单元测试失败。

    [TestMethod]
    public void Changing_Nutritionist_In_Disconnected_Context_Works()
    {
        Patient p;
        Nutritionist n;
        using (var c = new Context())
        {
            // Get a patient where I know p.Nutritionist.Id == 1 in database.
            p = c.Patients.Find(1);

            // Get some other nutritionist
            n = c.Nutritionists.Find(3);
        }
        using (var c = new Context())
        {
            //change patient's email and nutritionist 
            p.Email = "patient@domain.com";
            p.Nutritionist = n;

            c.Patients.Attach(p);
            c.Entry(p).State = EntityState.Modified;
            c.SaveChanges();
        }
        using (var c = new Context())
        {
            Assert.AreEqual(3,c.Patients.Find(1).Nutritionist.Id);
        }
    }

我预计这SaveChanges()将保存对患者p.Emailp.Nutritionist. 但在数据库中,只有电子邮件被更改,Nutritionist_Id字段继续显示旧值。因此,出于某种原因,dbContext 忽略了对导航属性的更改p.Nutritionist

SQL 探查器显示 EF 触发的以下 UPDATE 查询

exec sp_executesql N'UPDATE [dbo].[Patients]
SET [Name] = @0, [Email] = @1
WHERE ([Id] = @2)
',N'@0 nvarchar(max) ,@1 nvarchar(max) ,@2 int',@0=N'some name',@1=N'patient@domain.com',@2=1
go

想知道我可能会错过什么。

4

1 回答 1

2

是的,我可以使用显式属性p.NutritionistId,但我只是想成为一个纯粹主义者:)

我发现以下代码有效...

cn.Patients.Attach(p);
cn.Nutritionists.Attach(n);
cn.Entry(p).Reference(x => x.Nutritionist).Load();
p.Nutritionist = n;
cn.Entry(p).State = EntityState.Modified;
cn.SaveChanges();

似乎 EF 不会自动附加相关条目......p.Nutritionist在这种情况下。

同样正如Gert Arnold在上面的评论中提到的那样,它也没有加载它。

因此,显式加载p.Nutritionist然后使用附加实体更改其值使 EF 感到高兴。

我仍然想知道为什么 EF 不会自己做这一切,因为这似乎是一种逻辑编程意图,当我附加一个新实体并将其标记为EntityState.Modified时,我想保存它的全部,而不仅仅是标量属性。

于 2014-04-12T06:50:32.527 回答