在实体框架4.1(CodeFirst)中更新对子对象的引用

And*_*rke 9 c# entity-framework code-first ef-code-first

我正在尝试使用EntityFramework 4.1(CodeFirst)更新我之前保存的对象

Job类具有以下属性......

public class Job
{
    [key]
    public int Id { get; set; }
    public string Title { get; set; }
    public Project Project { get; set; }
    public JobType JobType { get; set; }
    public string Description { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

初始创建工作正常,但更新只提交对字符串的更改.

如果我改变的子对象,例如在JobType从地产JobTypeAJobTypeB-更改不会犯...

我不打算对JobType进行更改 - 仅限于Job.

using (var context = new JobContext())
{
    context.Jobs.Attach(job);
    context.Entry(job).State = EntityState.Modified;
    context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

看看SQL Profiler - 甚至没有为更新发送ID - 但它们是用于初始插入!

Sla*_*uma 16

将状态设置为Modified仅更新标量和复杂属性,而不是导航属性.这仅通过实体框架的变更检测.这意味着您需要从数据库加载原始文件:

using (var context = new JobContext())
{
    var originalJob = context.Jobs.Include(j => j.JobType)
        .Single(j => j.Id == job.Id);

    // Update scalar/complex properties
    context.Entry(originalJob).CurrentValues.SetValues(job);

    // Update reference
    originalJob.JobType = job.JobType;

    context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

您可能还可以在您的案例中利用一些"技巧":

using (var context = new JobContext())
{
    var jobType = job.JobType;
    job.JobType = null;

    context.JobTypes.Attach(jobType);
    context.Jobs.Attach(job);
    // change detection starts from here,
    // EF "thinks" now, original is JobType==null

    job.JobType = jobType;
    // change detection will recognize this as a change
    // and send an UPDATE to the DB

    context.Entry(job).State = EntityState.Modified; // for scalar/complex props

    context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

如果你想设置JobType为,它将无法工作null.

如果您将外键作为模型中的属性公开,这种情况会变得更加简单:JobTypeId在您的Job实体中,您的代码将起作用,因为FK属性是标量,将状态设置为Modified也会将此属性标记为已修改.