如何解决实体框架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;
}
}
解决方法
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
表具有两列ProtId
和ReportProtId
。但是您对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; }
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。