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 对象中。
再添加一个 属性 到您的项目实体:public Guid ClientId { get; set; }
。这与 public Client Client { get; set; }
并列。当您应用迁移时,您的项目 table 现在有 ClientId 来引用客户端(一对多关系,不是吗?)
应用迁移并确保 table 本身具有引用。
在您的方法中,在创建新项目时添加 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
我下面的代码可以很好地保存记录,但不能保存客户端。我没有收到任何错误消息,它会将记录保存到数据库,但不会与父客户端建立关系。在调试过程中,我逐步确认 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 对象中。
再添加一个 属性 到您的项目实体:
public Guid ClientId { get; set; }
。这与public Client Client { get; set; }
并列。当您应用迁移时,您的项目 table 现在有 ClientId 来引用客户端(一对多关系,不是吗?)应用迁移并确保 table 本身具有引用。
在您的方法中,在创建新项目时添加 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