簡體   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