无法使用 EF Core 在 ASP.NET Core 中创建相关实体

Can't create related entity in ASP.NET Core with EF Core

我在 Entity Framework Core 2.0 中创建相关实体时遇到问题。我刚刚创建了解决方案,包括一个 Asp.Net 核心后端项目和一个充当客户端的 UWP 项目。两种解决方案共享模型。这两个模型是:

public class UnitOfWork {
    public int UnitOfWorkId { get; set; }
    public string Name { get; set; }
    public Human Human { get; set; }
}

public class Human {
    public int HumanId { get; set; }
    public string Name { get; set; }
    public List<UnitOfWork> WorkDone { get; set; }
}

如您所见,模型非常简单。一个 human 有很多 units of work。顺便说一句,后端连接到 Azure SQL 数据库。我看过迁移 类,数据库模式对我来说看起来不错。

我遇到的问题是当我想使用 HTTP 创建引用现有 humanunit of work 时。控制器相当简单:

[HttpPost]
public UnitOfWork Post([FromBody] UnitOfWork unitOfWork) {
    using (var db = new DatabaseContext()) {
        db.UnitsOfWork.Add(unitOfWork);
        var count = db.SaveChanges();
        Console.WriteLine("{0} records saved to database", count);
    }
    return unitOfWork;
}

同样,这里没什么特别的。

如何创建工作单元并将其分配给现有人员?如果我以这种方式与现有的人一起尝试

var humans = await Api.GetHumans();
var firstHuman = humans.First();

var unitOfWorkToCreate = new UnitOfWork() {
    Name = TbInput.Text,
    Human = firstHuman,
};

我收到这个错误:

Cannot insert explicit value for identity column in table 'Humans' when IDENTITY_INSERT is set to OFF

我觉得将IDENTITY_INSERT设置为ON可以解决我的问题,但这不是我想要做的。在客户端中,我将 select 一个现有的 human,写下 unit of work 的名称,然后创建后者。这是正确的方法吗?

编辑:按照@Ivan Stoev 的回答,我更新了 UnitOfWork 控制器以附加 unitofwork.Human。这导致

Newtonsoft.Json.JsonSerializationException: 'Unexpected end when deserializing array. Path 'human.workDone', line 1, position 86.'

调查 - 看到 here - EFCore 期望在构造函数中创建集合(如 human.WorkDone),所以我做到了,不再进行空值反序列化。但是,现在我有一个自引用循环:

Newtonsoft.Json.JsonSerializationException: Self referencing loop detected with type 'PlainWorkTracker.Models.UnitOfWork'. Path 'human.workDone'.

有什么想法吗?谢谢!

相关操作属于 Saving Disconnected Entities 类别。

Add 方法将图中当前未跟踪的所有实体标记为新实体 (Added),然后 SaveChanges 将尝试将它们插入数据库。

您需要一种方法来告诉 EF unitOfWork.Human 是一个现有实体。实现这一点的最简单方法是在调用 Add:

之前将其 Attach (将其标记为 Unchanged,即存在)到上下文
db.Attach(unitOfWork.Human);
db.Add(unitOfWork);
// ...