繁体   English   中英

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

[英]Entity Framework OneToMany updating items - Missing foreign-key value

我想要在配置之前制作的一对多 rel

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 和日期分配给 newMeeting 对象,并且添加时您的 ReportProtId 为空。 像这样将 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 (),
    MeetingType = data.MeetingType ?? null,
    Date = data.Date ?? null,
    
    // Add this one
    ProtId = data.ProtId    
};

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

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

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

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

编辑-2:
如果你还没有在定义的配置为你的模型类OnModelCreating你的方法DbContext类,则迁移将使用实体框架的默认命名约定生成的表和列。

根据命名约定,您的Meeting类中的外键属性应命名为ReportId 由于实体框架没有找到该属性,它生成了一个供您用作外键 -

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

这就是您最终在迁移代码中(因此在数据库中)拥有ReportProtId列的方式,即使您的模型类中没有该属性。

如果需要,您仍然可以使用ProtId作为外键,但是您必须让实体框架知道您实际上希望该属性作为外键,即使不符合命名约定。 您可以通过向其添加[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; }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM