实体框架OneToMany更新项目-缺少外键值

问题描述

我想在配置之前与我建立一对多的关系

public class Report
{
    [Key]
    public string ProtId { get; set; }
    public Assessment Assessments { get; set; }
    public ManualReview ManualReview {get; set;}

    public ICollection<Meeting> Meetings {get; set;} 
}

public class Meeting
{   
    [Key]
    public Guid MeetId{get;set;}
    public MeetingType? MeetingType { get; set; }
    public DateTime? Date { get; set; }

    public string ProtId { get; set; }
    public Report Report{ get; set; }
}

我想添加新的会议,如果它不是由MeetId找到的,或者更新是使用下面的代码找到的MeetId,但是当我添加新的会议时,就像这种方法一样,它被添加到表中,我认为这是错误的,我的意思是我没有获取对父表(即报表表)的引用,因此在添加新会议后,ReportProtId为空。

此外,当我进行迁移时,它也在创建

migrationBuilder.CreateTable(
    name: "Meetings",columns: table => new
    {
        MeetId = table.Column<Guid>(nullable: false),MeetingType = table.Column<int>(nullable: true),Date = table.Column<DateTime>(nullable: true),ProtId= table.Column<string>(nullable: true),ReportProtId = table.Column<string>(nullable: true)
    },constraints: table =>
    {
        table.PrimaryKey("PK_Meetings",x => x.MeetId);
        table.ForeignKey(
            name: "FK_Meetings_Report_ReportProtId",column: x => x.ReportProtId,principalTable: "Studies",principalColumn: "ProtId",onDelete: referentialAction.Restrict);
    });

添加/更新会议的方法

[HttpPut ("meetings/{id}")]
public async Task<IActionResult> UpdateMeetings (string id,[FromBody] Meeting data)
{
    var meeting = await _liteContext.Meetings.FirstOrDefaultAsync (m => m.MeetId == data.MeetId);

    if (meeting == null) {
        var newMeeting = new Meeting {
       
        MeetId = new Guid (),MeetingType = data.MeetingType ?? null,Date = data.Date ?? null,};
        _liteContext.Meetings.Add (newMeeting);
    }
    if (meeting != null) {
       
        meeting.MeetingType = data.MeetingType;
        meeting.Date = data.Date;

        _liteContext.Meetings.Update (meeting);
    }
    try {
        await _liteContext.SaveChangesAsync ();
        return NoContent ();
    } catch (dbupdateConcurrencyException) {

        throw new Exception ();
    }
}

已编辑

[HttpGet("lite")]
        public async Task<dynamic> GetData()
        {
            try
            {
                var data = await _liteContext.Reports
                    .Include(a => a.Assessments)
                    .Include(m => m.Meetings) // empty array
                    .Include(mr => mr.ManualReview)
                    .ToListAsync();

                return data;
            }
            catch (System.Exception)
            {

                throw;
            }
        }

解决方法

Meetings表中的

ReportProtId列可为空,并且在添加新会议时使用UpdateMeetings方法时,您仅将MeetId,MeetingType和Date分配给newMeeting对象,而添加时ReportProtId为null。像这样将ReportProtId分配给newMeeting对象:

 if (meeting == null) {
                var newMeeting = new Meeting {
               
                MeetId = new Guid (),MeetingType = data.MeetingType ?? null,Date = data.Date ?? null,ReportProtId = data.ReportProtId
                };
                _liteContext.Meetings.Add (newMeeting);
            }
,

创建新会议时,请设置ProtId值-

var newMeeting = new Meeting { 
     
    MeetId = new Guid (),// Add this one
    ProtId = data.ProtId    
};

希望您能从客户那里收到它。

编辑:
根据您的迁移代码,Meetings表具有两列ProtIdReportProtId。但是您对Meeting的模型类定义仅显示ProtId属性。

如果您确实在ReportProtId类中拥有Meeting属性,请设置该属性的值(而不是ProtId的属性),因为您已将ReportProtId列定义为外部键,而不是ProtId

如果Meeting类实际上没有ReportProtId属性,那么您需要更新迁移代码并相应地更新数据库。

编辑2:
如果尚未在OnModelCreating类的DbContext方法中为模型类定义任何配置,则Migration将使用Entity Frameworks的默认命名约定来生成表和列。

根据命名约定,您的Meeting类中的外键属性应命名为ReportId。由于Entity Framework找不到该属性,因此它为您生成了一个用作外键-

Referenced class name (Report) + Primary-key name of referenced class (ProtId) = ReportProtId

即使您在模型类中没有该属性,也仍然会在迁移代码中(因此在数据库中)有ReportProtId列。

如果需要,您仍然可以使用ProtId作为外键,但是即使不符合命名约定,您也必须让Entity Framework知道您实际上希望将该属性作为外键。 。您可以通过向其添加[ForeignKey("Report")]属性来实现。

因此,将您的Meeting类定义更改为-

public class Meeting
{   
    [Key]
    public Guid MeetId{get;set;}
    public MeetingType? MeetingType { get; set; }
    public DateTime? Date { get; set; }

    public string ReprotId { get; set; }    // Modified
    public Report Report{ get; set; }
}

或至-

// this import will be required
// using System.ComponentModel.DataAnnotations.Schema;

public class Meeting
{
    [Key]
    public Guid MeetId { get; set; }
    public string MeetingType { get; set; }
    public DateTime? Date { get; set; }

    [ForeignKey("Report")]                   // Added
    public string ProtId { get; set; }
    public Report Report { get; set; }
}