实体框架代码首次更新记录不保存父母

问题描述:

我的代码在下面保存记录的罚款,但它不保存客户端。我没有得到任何错误,它将记录保存到数据库中,但不会与父客户端建立关系。在调试时,我已经逐步确定了var客户端实际上包含客户端对象。实体框架代码首次更新记录不保存父母

任何帮助非常感谢!

反正这里是我的代码:

using (var context = new TDBContext()) 
     { 
      if (SelectedProject != null) 
      { 
       var client = (from x in context.Clients 
           where x.ID == (Guid) comboClient.SelectedValue 
           select x).FirstOrDefault(); 

       Project project = new Project() 
       { 
        ID = (Guid) SelectedProject, 
        ProjectCode = textProjectCode.Text, 
        Client = client, 
        ProjectStart = dateProjectStart.SelectedDate, 
        Active = checkActive.IsChecked 
       }; 

       context.Projects.Attach(project);  
       context.Entry(project).State = EntityState.Modified; 
       context.SaveChanges(); 
      } 
      else 
      { 
       MessageBox.Show("Project ID not loaded!", "Error!", MessageBoxButton.OK, MessageBoxImage.Error); 
      } 
     } 

项目单位:

public Project() 
    { 

    } 

    [Key] 
    public Guid ID { get; set; }  
    public string ProjectCode { get; set; } 
    public Client Client { get; set; } 
    public DateTime? ProjectStart { get; set; } 
    public bool? Active { get; set; } 

客户端实体:

public Client() 
    { 

    } 
    [Key] 
    public Guid ID { get; set; } 
    public string ClientName { get; set; } 
    public byte[] ClientLogo { get; set; } 

    public ICollection<Project> Projects { get; set; } 
+0

的做这件事的一个时髦的一种方式(我会获取客户端和更新其子集),但它可能会工作,如果你还设置Project.Client的实体状态修改为好。另外,当我指望父记录的存在时,我更喜欢'First()'到'FirstOrDefault()'。我至少会确定它不是null。 –

编辑(终于得到了它的工作):

我创建了一个单独的方法来更新客户端。我从我的主要保存方法中调用它。这每次都有效。我敢肯定,我可以做得更好(即都在同一个方法):

private void SaveClient() 
    { 
     using (var context = new PDBContext()) 
     { 
      var client = (from x in context.Clients 
          where x.ID == (Guid) comboClient.SelectedValue 
          select x).FirstOrDefault(); 

      var project = (from x in context.Projects 
          where x.ID == SelectedProject 
          select x).FirstOrDefault(); 

      project.Client = client; 

      context.Projects.Attach(project); 

      context.Entry(project).State = EntityState.Modified; 

      context.SaveChanges(); 
     } 

     PopulateClientCombo(); 
    } 

你必须在客户端Id列只是不分配客户参考。 EF足够聪明,可以检查ClientId何时存在并且具有与客户端导航属性不同的id,但是如果id为空,它将完全忽略该Client导航属性。

编辑

啊,然后调用context.Projects.Add(项目),而不是将其更改为修改。

+0

尝试Client.ID = client.ID但它不起作用。我得到“无效的初始化成员声明”。什么是正确的方法来做到这一点? – Salbrox

+0

项目实体本身的客户端ID属性。即project.ClientId = client.Id。 –

+0

我没有客户端ID属性我有一个客户端,它是项目的父实体。他们处于1-n关系。 – Salbrox

我不是很确定你使用EF的,但我会尽力给这个问题一个镜头。请注意,这与您的方法完全不同。简而言之,我将创建/获取客户端标识并将其添加到正在添加的新项目对象中。

  1. 多了一个属性添加到您的项目实体:public Guid ClientId { get; set; }。这与public Client Client { get; set; }并列。当您应用迁移时,您的项目表现在具有ClientId以引用客户端(一对多关系,是不是?)

  2. 应用迁移并确保表本身具有引用。

  3. 在您的方法中,在创建新项目时添加ClientId。这应该够了。

    Project project = new Project() 
    { 
        ID = (Guid) SelectedProject, 
        ProjectCode = textProjectCode.Text, 
        ClientId = (Guid)comboClient.SelectedValue, // Your client's Guid. Make sure this record exists in the database. 
        ProjectStart = dateProjectStart.SelectedDate, 
        Active = checkActive.IsChecked 
    }; 
    

这是我和我的项目做。当你查询,你加载数据和EntityFramework有方法为你做。另请参见:Loading Related Data