EF Core 不会在子 table 中插入外键
EF Core does not insert foreign key in child table
我有以下 classes:
public class PresentingComplaintModel
{
// for presenting complaints only
[Key]
public int ComplaintId { get; set; }
public string Complaint { get; set; }
public int? PatientId { get; set; }
public Patient Patient { get; set; }
public DateTime CreationDate { get; set; }
public List<PatientComplaintQuestionAnswers> PatientComplaintQuestionAnswers { get; set; }
}
这个class和这个class有一对多的关系:
public class PatientComplaintQuestionAnswers
{
[Key]
public int Id { get; set; }
public int? PresentingComplaintQuestionId { get; set; }
public PresentingComplaintQuestionModel PresentingComplaintQuestionModel { get; set; }
public bool Answer { get; set; }
public int ComplaintId { get; set; } //from PresentingComplaintModel
public PresentingComplaintModel PresentingComplaintModel {get;set;}
}
这个class有两个外键:PresentingComplaintQuestionId
和ComplaintId
。问题是当我将 PresentingComplaintModel
对象插入数据库时,子对象 table (PatientComplaintQuestionAnswers
) 接收数据但 ComplaintId
始终设置为 0。这意味着ComplaintId
不是从 PresentingComplaintModel
class 的主键填充的。
我希望它具有非零主键值。如何解决这个问题?
PresentingComplaintModel
水合如下。这里 ComplaintId
始终为 0,因为正在创建新记录。
PresentingComplaintModel complaint = new();
List<PresentingComplaintQuestionModel> MasterQuestions { get; set; }
public PatientComplaintQuestionAnswers selectedItem1 { get; set; }
protected override async Task OnInitializedAsync()
{
complaint.PatientComplaintQuestionAnswers = new List<PatientComplaintQuestionAnswers>();
complaint.Complaint = "";
complaint.CreationDate = DateTime.Now;
complaint.PatientId = AppState.SelectedPatient.PatientId;
MasterQuestions = await DataService.GetPresentingComplaintQuestionsAsync(); //get master questions.
foreach (var q in MasterQuestions)
{
var ans = new PatientComplaintQuestionAnswers();
ans.ComplaintId = complaint.ComplaintId;
ans.PresentingComplaintQuestionId = q.PresentingComplaintQuestionId;
ans.Answer = false;
ans.PresentingComplaintQuestionModel = q;
ans.PresentingComplaintModel = complaint; //reciprocal hydrating. see
complaint.PatientComplaintQuestionAnswers.Add(ans);
}
}
然后保存到数据库:
var res = await DataService.UpdatePresentingComplaintAsync(complaint);
...
...
public async Task<bool> UpdatePresentingComplaintAsync(PresentingComplaintModel complaint)
{
int res = 0;
using (var scope = _scopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
try
{
context.PresentingComplaints.Update(complaint);
res = await context.SaveChangesAsync();
}
catch (Exception ex)
{
}
}
if (res > 0)
return true;
else
return false;
}
在数据库端,我看到了这些插入。请注意,ComplaintId
列中全为 0:
通常这是缺乏“相互”补水。
public class MyParent()
{
public MyParent()
{
this.TheKids = new List<MyChild>();
}
public long MyParentKey {get; set;} /* PK */
public ICollection<MyChild> TheKids {get;set;}
}
public class MyChild()
{
public long MyChildKey {get; set;} /* PK */
public long MyParentKey {get;set;} /* FK to MyParent */
public MyParent TheMyParent {get;set;} /* navigation property to MyParent */
}
当你合成“数据库中尚不存在”的实体时..你必须做一些“互惠”
MyParent p1 = new MyParent();
MyChild c1 = new MyChild();
/* most people do this */
p1.TheKids.Add(c1);
/* the "reciprocal" that is sometimes missed */
c1.TheMyParent = p1;
(或者可以是 vice-versa,child 设置了“TheMyParent”,但 child 没有添加到 MyParent.TheKids 集合)
试一试(确保所有倒数都已设置)
注意,我没有设置 MyChild.MyParentKey。
如果 MyParent 还不存在,我会这样做。
..
EF 允许使用 FK 标量的“捷径”...如果它们是已知的。
例如
public class Employee()
{
public long EmployeeKey {get; set;} /* PK */
public string LastName {get; set;}
public string FirstName {get; set;}
public long ParentDepartmentKey {get;set;} /* FK to Department */
public Department ParentDepartment {get;set;} /* navigation property to Department */
}
如果我有上述 class,并且当我添加一个新员工时......并且该员工必须将其部门设置为现有部门。
然后我可以做类似
的事情
Employee emp = new Employee();
emp.LastName = "Smith";
emp.FirstName = "Mary";
emp.ParentDepartmentKey = 333; /* an already existing Department */
这样一来,我就不必完全补充 emp.ParentDepartment OBJECT(导航 属性)来添加员工。
因此,在将 object-graph 提供给 EF dbcontext 并保留更改之前,您需要了解“存在的内容和尚不存在的内容”。
好的,我找到了解决方法。在这种情况下,EFCore 似乎没有正确设置外键列。所以我用明确的 ForeignKey 属性修改了 PatientComplaintQuestionAnswers class:
public class PatientComplaintQuestionAnswers
{
[Key]
public int Id { get; set; }
public int? PresentingComplaintQuestionId { get; set; }
public PresentingComplaintQuestionModel PresentingComplaintQuestionModel { get; set; }
public bool Answer { get; set; }
public int ComplaintId { get; set; } //from PresentingComplaintModel
public PresentingComplaintModel PresentingComplaintModel {get;set;}
}
到
public class PatientComplaintQuestionAnswers
{ //patient answers these questions in the patient presenting complaint form
[Key]
public int Id { get; set; }
[ForeignKey("PresentingComplaintQuestionModel")]
public int? PresentingComplaintQuestionId { get; set; }
public PresentingComplaintQuestionModel PresentingComplaintQuestionModel { get; set; }
public bool Answer { get; set; }
[ForeignKey("PresentingComplaintModel")]
public int ComplaintId { get; set; } //from PresentingComplaintModel
public PresentingComplaintModel PresentingComplaintModel {get;set;}
}
这修复了关系,EFCore 也没有生成无关的列。
我有以下 classes:
public class PresentingComplaintModel
{
// for presenting complaints only
[Key]
public int ComplaintId { get; set; }
public string Complaint { get; set; }
public int? PatientId { get; set; }
public Patient Patient { get; set; }
public DateTime CreationDate { get; set; }
public List<PatientComplaintQuestionAnswers> PatientComplaintQuestionAnswers { get; set; }
}
这个class和这个class有一对多的关系:
public class PatientComplaintQuestionAnswers
{
[Key]
public int Id { get; set; }
public int? PresentingComplaintQuestionId { get; set; }
public PresentingComplaintQuestionModel PresentingComplaintQuestionModel { get; set; }
public bool Answer { get; set; }
public int ComplaintId { get; set; } //from PresentingComplaintModel
public PresentingComplaintModel PresentingComplaintModel {get;set;}
}
这个class有两个外键:PresentingComplaintQuestionId
和ComplaintId
。问题是当我将 PresentingComplaintModel
对象插入数据库时,子对象 table (PatientComplaintQuestionAnswers
) 接收数据但 ComplaintId
始终设置为 0。这意味着ComplaintId
不是从 PresentingComplaintModel
class 的主键填充的。
我希望它具有非零主键值。如何解决这个问题?
PresentingComplaintModel
水合如下。这里 ComplaintId
始终为 0,因为正在创建新记录。
PresentingComplaintModel complaint = new();
List<PresentingComplaintQuestionModel> MasterQuestions { get; set; }
public PatientComplaintQuestionAnswers selectedItem1 { get; set; }
protected override async Task OnInitializedAsync()
{
complaint.PatientComplaintQuestionAnswers = new List<PatientComplaintQuestionAnswers>();
complaint.Complaint = "";
complaint.CreationDate = DateTime.Now;
complaint.PatientId = AppState.SelectedPatient.PatientId;
MasterQuestions = await DataService.GetPresentingComplaintQuestionsAsync(); //get master questions.
foreach (var q in MasterQuestions)
{
var ans = new PatientComplaintQuestionAnswers();
ans.ComplaintId = complaint.ComplaintId;
ans.PresentingComplaintQuestionId = q.PresentingComplaintQuestionId;
ans.Answer = false;
ans.PresentingComplaintQuestionModel = q;
ans.PresentingComplaintModel = complaint; //reciprocal hydrating. see
complaint.PatientComplaintQuestionAnswers.Add(ans);
}
}
然后保存到数据库:
var res = await DataService.UpdatePresentingComplaintAsync(complaint);
...
...
public async Task<bool> UpdatePresentingComplaintAsync(PresentingComplaintModel complaint)
{
int res = 0;
using (var scope = _scopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
try
{
context.PresentingComplaints.Update(complaint);
res = await context.SaveChangesAsync();
}
catch (Exception ex)
{
}
}
if (res > 0)
return true;
else
return false;
}
在数据库端,我看到了这些插入。请注意,ComplaintId
列中全为 0:
通常这是缺乏“相互”补水。
public class MyParent()
{
public MyParent()
{
this.TheKids = new List<MyChild>();
}
public long MyParentKey {get; set;} /* PK */
public ICollection<MyChild> TheKids {get;set;}
}
public class MyChild()
{
public long MyChildKey {get; set;} /* PK */
public long MyParentKey {get;set;} /* FK to MyParent */
public MyParent TheMyParent {get;set;} /* navigation property to MyParent */
}
当你合成“数据库中尚不存在”的实体时..你必须做一些“互惠”
MyParent p1 = new MyParent();
MyChild c1 = new MyChild();
/* most people do this */
p1.TheKids.Add(c1);
/* the "reciprocal" that is sometimes missed */
c1.TheMyParent = p1;
(或者可以是 vice-versa,child 设置了“TheMyParent”,但 child 没有添加到 MyParent.TheKids 集合)
试一试(确保所有倒数都已设置)
注意,我没有设置 MyChild.MyParentKey。
如果 MyParent 还不存在,我会这样做。
..
EF 允许使用 FK 标量的“捷径”...如果它们是已知的。
例如
public class Employee()
{
public long EmployeeKey {get; set;} /* PK */
public string LastName {get; set;}
public string FirstName {get; set;}
public long ParentDepartmentKey {get;set;} /* FK to Department */
public Department ParentDepartment {get;set;} /* navigation property to Department */
}
如果我有上述 class,并且当我添加一个新员工时......并且该员工必须将其部门设置为现有部门。
然后我可以做类似
的事情Employee emp = new Employee();
emp.LastName = "Smith";
emp.FirstName = "Mary";
emp.ParentDepartmentKey = 333; /* an already existing Department */
这样一来,我就不必完全补充 emp.ParentDepartment OBJECT(导航 属性)来添加员工。
因此,在将 object-graph 提供给 EF dbcontext 并保留更改之前,您需要了解“存在的内容和尚不存在的内容”。
好的,我找到了解决方法。在这种情况下,EFCore 似乎没有正确设置外键列。所以我用明确的 ForeignKey 属性修改了 PatientComplaintQuestionAnswers class:
public class PatientComplaintQuestionAnswers
{
[Key]
public int Id { get; set; }
public int? PresentingComplaintQuestionId { get; set; }
public PresentingComplaintQuestionModel PresentingComplaintQuestionModel { get; set; }
public bool Answer { get; set; }
public int ComplaintId { get; set; } //from PresentingComplaintModel
public PresentingComplaintModel PresentingComplaintModel {get;set;}
}
到
public class PatientComplaintQuestionAnswers
{ //patient answers these questions in the patient presenting complaint form
[Key]
public int Id { get; set; }
[ForeignKey("PresentingComplaintQuestionModel")]
public int? PresentingComplaintQuestionId { get; set; }
public PresentingComplaintQuestionModel PresentingComplaintQuestionModel { get; set; }
public bool Answer { get; set; }
[ForeignKey("PresentingComplaintModel")]
public int ComplaintId { get; set; } //from PresentingComplaintModel
public PresentingComplaintModel PresentingComplaintModel {get;set;}
}
这修复了关系,EFCore 也没有生成无关的列。