EF核心一对多添加新对象

时间:2019-01-19 17:25:50

标签: c# asp.net-core asp.net-core-mvc ef-core-2.1

我尝试了很多方法,但是每种解决方案仍然遇到不同类型的错误。我试图停止跟踪,尝试自己添加challenge,更新competition,但它们似乎都无法正常工作。

我基本上要面对许多挑战的比赛,在这种情况下,已经存在1 competition和1 challenge,并且我要添加另外一个具有外键链接的challenge competition。我知道我之前曾问过类似的question,但这是为了批量创建1个比赛到多个类别。我认为这更像是更新操作,似乎没有用。非常感谢您的帮助! :)

  

InvalidOperationException:实体类型“挑战”的实例   无法跟踪,因为另一个实例具有相同的键值   {'ID'}已被跟踪。附加现有实体时,   确保只有一个具有给定键值的实体实例是   附上。考虑使用   'DbContextOptionsBuilder.EnableSensitiveDataLogging'以查看   冲突的键值。

Competition模型类别:

public class Competition
{
    [Key]
    public int ID { get; set; }

    public ICollection<CompetitionCategory> CompetitionCategories { get; set; }
    public ICollection<Challenge> Challenges { get; set; }
}

Challenge模型类别:

public class Challenge
{
    [Key]
    public int ID { get; set; }

    [ForeignKey("CompetitionID")]
    public int CompetitionID { get; set; }
    [Display(Name = "Competition Category")]
    [ForeignKey("CompetitionCategoryID")]
    public int CompetitionCategoryID { get; set; }
}

控制器:

public async Task<IActionResult> Create([Bind("ID,XXX,CompetitionID,CompetitionCategoryID")] Challenge challenge)
{
    var competition = await _context.Competitions
    .Include(c => c.CompetitionCategories)
    .Include(c1 => c1.Challenges)
    .AsNoTracking()
    .FirstOrDefaultAsync(m => m.ID == challenge.CompetitionID);

    if (ModelState.IsValid)
    {
        //_context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
        competition.Challenges.Add(challenge);

        _context.Update(competition);
        _context.Entry(competition).State = EntityState.Detached;
        _context.Entry(competition.Challenges).State = EntityState.Detached;
        await _context.SaveChangesAsync();
        //_context.Add(challenge);
        //await _context.SaveChangesAsync();
        //return RedirectToAction(nameof(Index));
        return RedirectToAction("Index", "Challenges", new { id = challenge.CompetitionID });
    }

     return View();
 }

更新:我实际上已经尝试仅添加challenge本身,但是它还会引发另一个错误。真的很迷茫。

  

SqlException:无法为身份列插入显式值   IDENTITY_INSERT设置为OFF时,表“挑战”。   System.Data.SqlClient.SqlCommand + <> c.b__122_0(任务   结果)

     

DbUpdateException:更新条目时发生错误。看到   内部异常的详细信息。   Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection   连接,CancelationToken cancelToken)

更新2:将ID从绑定中删除是可行的,因为传入了一些未知的ID值并对其进行了跟踪。 Ivan关于使用外键添加新对象的答案是正确的。

public async Task<IActionResult> Create([Bind("XXX,CompetitionID,CompetitionCategoryID")] Challenge challenge)
{
    //Codes here
    _context.Add(challenge);
    await _context.SaveChangesAsync();
}

1 个答案:

答案 0 :(得分:2)

使用断开连接的实体并不容易,并且需要不同的技术,具体取决于实体模型中导航的存在与否/反向导航以及FK属性。

您的Challenge类具有显式的FK属性,而没有导航属性。像这样添加新对象是最简单的操作-只需调用DbContext.AddDbSet.Add

_context.Add(challenge);
await _context.SaveChangesAsync();

但是,您遇到的异常使我认为Challenge方法接收的Create对象具有PK属性Id,该属性填充了现有{{1} }。如果您确实要添加新的Challenge并且Challenge是自动生成的,请从绑定中排除Id或确保在调用{之前将其设置为Id(零)。 {1}}。

有关更多信息,请参阅EF Core文档中的Disconnected Entities和相关链接。