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有两个外键:PresentingComplaintQuestionIdComplaintId。问题是当我将 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 也没有生成无关的列。