Entity Framework Code First 更新记录未保存父项

Entity Framework Code First Updating Record is Not Saving Parent

我下面的代码可以很好地保存记录,但不能保存客户端。我没有收到任何错误消息,它会将记录保存到数据库,但不会与父客户端建立关系。在调试过程中,我逐步确认 var client 实际上包含一个客户端对象。

非常感谢任何帮助!

无论如何这是我的代码:

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; } 

您必须分配 ClientId 列,而不仅仅是客户引用。 EF 足够聪明,可以检查 ClientId 何时存在并且具有与客户端导航 属性 不同的 ID,但如果 id 为空,它将完全忽略客户端导航 属性。

编辑

啊,那就调用context.Projects.Add(project)而不是改成Modified.

编辑(终于成功了):

我创建了一个单独的方法来更新客户端。我从我的主要保存方法中调用它。现在每次都有效。我确信我可以做得更好(即全部采用相同的方法):

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();
    }

我不太确定你对 EF 的使用,但我会尝试解决这个问题。请注意,这与您的方法完全不同。简而言之,我将 create/get Client's Id 并将其添加到正在添加的新 Project 对象中。

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

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

  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