gpt4 book ai didi

c# - 当子项具有身份 key 时,如何使用 EF 将多个子实体添加到对象?

转载 作者:可可西里 更新时间:2023-11-01 08:47:27 26 4
gpt4 key购买 nike

我们正在使用 EF5 和 SQL Server 2012 以下两个类:

public class Question
{
public Question()
{
this.Answers = new List<Answer>();
}
public int QuestionId { get; set; }
public string Title { get; set; }
public virtual ICollection<Answer> Answers { get; set; }

}
public class Answer
{
public int AnswerId { get; set; }
public string Text { get; set; }
public int QuestionId { get; set; }
public virtual Question Question { get; set; }
}

映射如下:

public class AnswerMap : EntityTypeConfiguration<Answer>
{
public AnswerMap()
{
// Primary Key
this.HasKey(t => t.AnswerId);

// Identity
this.Property(t => t.AnswerId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

数据库 DDL

CREATE TABLE Answer (
[AnswerId] INT IDENTITY (1, 1) NOT NULL,
[QuestionId] INT NOT NULL,
[Text] NVARCHAR(1000),
CONSTRAINT [PK_Answer] PRIMARY KEY CLUSTERED ([AnswerId] ASC)
)";

这是我尝试过的结果:

这对一个 child 有效:

var a = new Answer{
Text = "AA",
QuestionId = 14
};
question.Answers.Add(a);
_uow.Questions.Update(question);
_uow.Commit();

这不适用于多个 child :

错误:ObjectStateManager 中已存在具有相同键的对象。 ObjectStateManager 无法跟踪具有相同键的多个对象。

var a = new Answer{
AnswerId = 0,
Text = "AAA",
QuestionId = 14
};
var b = new Answer {
AnswerId = 0,
Text = "BBB",
QuestionId = 14
};
question.Answers.Add(a);
question.Answers.Add(b);
_uow.Questions.Update(question);
_uow.Commit();

这不适用于多个 child :

它创建 AnswerID 的 1000 和 1001,但我希望数据库创建新的 ID。

var a = new Answer{
AnswerId = 1000,
Text = "AAA",
QuestionId = 14
};
var b = new Answer {
AnswerId = 1001,
Text = "BBB",
QuestionId = 14
};
question.Answers.Add(a);
question.Answers.Add(b);
_uow.Questions.Update(question);
_uow.Commit();

不起作用:

编译错误。无法将 null 转换为 int

var a = new Answer{
AnswerId = null,
Text = "AAA",
QuestionId = 14
};
var b = new Answer
{
AnswerId = null,
Text = "BBB",
QuestionId = 14
};
question.Answers.Add(a);
question.Answers.Add(b);
_uow.Questions.Update(question);
_uow.Commit();

不起作用:

ObjectStateManager 无法跟踪具有相同键的多个对象。

var a = new Answer{
Text = "AAA",
QuestionId = 14
};
var b = new Answer
{
Text = "BBB",
QuestionId = 14
};
question.Answers.Add(a);
question.Answers.Add(b);
_uow.Questions.Update(question);
_uow.Commit();

在我的应用程序中,我在客户端生成了一个或多个新的 Answer 对象,然后将这些对象发送到服务器。以上我正在模拟将要发生的事情,但没有将客户添加到问题中。请注意,将所有 Answers 添加到 Question 对象是在客户端完成的,然后以 JSON 字符串的形式传送到服务器。然后它被反序列化为一个问题对象,如下所示:

public HttpResponseMessage PutQuestion(int id, Question question) {
_uow.Questions.Update(question);
_uow.Commit();

我希望每个 Answer 对象都使用 新身份 ID 创建,以便将这些添加到 Question 对象并以正常方式返回 Question 对象。

我不知道如何做到这一点。到目前为止,我所有的简单测试都不起作用。请注意,这是我们小组成员较早提出的问题的变体,该问题不太清楚,我正试图将其关闭。这个问题我希望更清楚。

注意事项:

更新的编码方式如下:

public virtual void Update(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State == EntityState.Detached)
{
DbSet.Attach(entity);
}
dbEntityEntry.State = EntityState.Modified;
}

最佳答案

我也遇到了相同的身份“限制”。事实证明,如果您添加父项和任何子项,EF 可以处理将父项和子项全部添加在一起的事实。当您更新父项并同时插入两个子项时,您会遇到问题。如果附加父项,EF 将自动拾取这两个子项并附加它们,无论您是否愿意。因为我们希望它自动生成 Id,所以我们不会设置子项的主键。但是,当父项是更新时,EF 无法处理具有相同主键的项目并爆炸,因为两个子项的 PK 相同,均为 0。

我找到的解决此问题的唯一方法是手动将子项的 ID 设置为不同的数字。我通常将第一个 child 的 Id 设置为 -1,然后为第二个 child 设置 -2,依此类推。这将导致 EF 保存子项,并且由于数据库上运行的身份, key 将自动更新,因为 -1 和 -2 不是有效的身份值。

但是,如果您的等级为 3 级或以上,这将造成极大的痛苦。您不仅必须更新每个 child 的 PK,而且还必须将其任何 child 的 FK 更新为这个新的 -1 或 -2 值。否则会再次保存失败!

我看到的唯一其他选项实际上只是一次插入一个子对象并调用保存,这样上下文就不会处理多个具有相同 PK 的对象,但这违背了 ORM 的目的。 ..

关于c# - 当子项具有身份 key 时,如何使用 EF 将多个子实体添加到对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17946616/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com