简体   繁体   中英

Entity Framework OneToMany updating items - Missing foreign-key value

I want to have one to many rel which i made with before config

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; }
}

I want to add new meeting if it was not found by MeetId or update is MeetId found with below code but when i add new meeting it is added to table like in this method i think something is wrong there i mean i do not get reference to Parent table which is Report table so after adding new meeting ReportProtId is null.

Also when i make migration it is creating this

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);
    });

Method to add/update meetings

[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 ();
    }
}

EDITED

[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 column in Meetings table is nullable and in your UpdateMeetings method while adding a new Meeting you are only assigning MeetId, MeetingType, and Date to newMeeting object and your ReportProtId is null while adding. Assign ReportProtId to newMeeting object like this:

 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);
            }

When creating new Meeting, set the ProtId value -

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

I hope you are receiving it from the client.

Edit :
According to your migration code, the Meetings table has two columns ProtId and ReportProtId . But your model class definition for Meeting shows only the ProtId property.

If you do have a ReportProtId property in Meeting class, set the value for that property (not for ProtId ) since you have defined ReportProtId column as the foreign-key, not ProtId .

If the Meeting class in fact doesn't have the ReportProtId property then you need to update your Migration code and update the database accordingly.

Edit-2 :
If you haven't defined any configuration for your model classes in the OnModelCreating method of your DbContext class, then Migration will use Entity Frameworks' default naming convention to generate the tables and columns.

According to the naming convention, the foreign-key property in your Meeting class should be named ReportId . Since Entity Framework didn't find that property, it generated one for you to use as foreign-key -

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

That's how you ended up having the ReportProtId column in your Migration code (and hence in the database) even though you don't have that property in your model class.

You can still use ProtId as foreign-key if you want, but then you have to let Entity Framework know you in fact want that property as foreign-key, even if doesn't conform to the naming convention. You can do that by add the [ForeignKey("Report")] attribute to it.

So, change your Meeting class definition either to -

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; }
}

or to -

// 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; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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