【问题标题】:How can I add a new object to an existing Entity, PUT the data and have EF add it to my database?如何将新对象添加到现有实体、PUT 数据并让 EF 将其添加到我的数据库中?
【发布时间】:2013-07-30 07:39:41
【问题描述】:

我正在使用 EF5、SQL Server 2012 和 Web 前端。在服务器上,我有以下两个类:

public class Question
{
    public Question()
    {
        this.Answers = new List<Answer>();
    }
    public int QuestionId { get; set; }
    public string Title { get; set; }
    public string Answer { 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; }
}

我在前端应用程序中检索了一个问题,添加了一个空答案:

   var emptyAnswer = { "answerId"; null, "text": "xx", "questionId": formData.questionId};
   formData.answers.push(emptyAnswer);

然后我对服务器做了一个 PUT 并注意到当它进入服务器时 answerId 被正确设置为 null。

    public HttpResponseMessage PutQuestion(int id, Question question)
    {
        var a = question;
    }

数据由我的 ASP.NET WebApi 控制器接收,但是当我检查新创建的答案对象时,它现在是我的问题的一部分,它的 AnswerId 为 0

谁能告诉我为什么它从 null > 0 改变?问题是当我现在做一个更新实体 框架给了我一个错误,因为它期望新创建的答案没有设置它的 AnswerId。

请注意。我在对象到达实体框架之前进行检查。我提到我正在使用它,但此时我认为它还没有出现,因为我只是检查了 poco 类。下面提到了该字段不可为空。但是,当我创建一个新对象时,有效负载是相似的,例如,当我创建一个“内容”对象时,我将字段设置为 null 并且它保持为 null。

这是迄今为止我的测试结果。我把前端从循环中去掉了,所以一切都更清楚了:

作品:

var a = new Answer{
    Correct = false,
    Response = false,
    Text = "AA",
    Image = "DDD",
    QuestionId = question.QuestionId
};
question.Answers.Add(a);
_uow.Questions.Update(question);
_uow.Commit();

不起作用:ObjectStateManager 中已存在具有相同键的对象。 ObjectStateManager 无法跟踪具有相同键的多个对象。

var a = new Answer{
    AnswerId = 0,
    Correct = false,
    Response = false,
    Text = "AAA",
    Image = "DDD",
    QuestionId = question.QuestionId
};
var b = new Answer
{
    AnswerId = 0,
    Correct = false,
    Response = false,
    Text = "BBB",
    Image = "EEE",
    QuestionId = question.QuestionId
};

无法正常工作。它不会创建新的实体值。它只使用 1000 和 1001

var a = new Answer{
    AnswerId = 1000,
    Correct = false,
    Response = false,
    Text = "AAA",
    Image = "DDD",
    QuestionId = question.QuestionId
};
var b = new Answer
{
    AnswerId = 1001,
    Correct = false,
    Response = false,
    Text = "BBB",
    Image = "EEE",
    QuestionId = question.QuestionId
};

不起作用:编译器错误。无法将 null 转换为 int

var a = new Answer{
    AnswerId = null,
    Correct = false,
    Response = false,
    Text = "AAA",
    Image = "DDD",
    QuestionId = question.QuestionId
};
var b = new Answer
{
    AnswerId = null,
    Correct = false,
    Response = false,
    Text = "BBB",
    Image = "EEE",
    QuestionId = question.QuestionId
};

不起作用:ObjectStateManager 无法使用相同的键跟踪多个对象。

var a = new Answer{
    Correct = false,
    Response = false,
    Text = "AAA",
    Image = "DDD",
    QuestionId = question.QuestionId
};
var b = new Answer
{
    Correct = false,
    Response = false,
    Text = "BBB",
    Image = "EEE",
    QuestionId = question.QuestionId
};

【问题讨论】:

  • 在您的数据库中,ID 是 1 索引的(即从 1,2,3 与 0,1,2 开始),因此无论如何您都无法输入零索引。
  • 这取决于列是否配置为标识。如果该列不是标识列,则 0 是一个完全有效的值。
  • 我正在检查对象并注意到它在到达 EF 之前为 0,而它只是一个 poco 类。

标签: c# asp.net-mvc json entity-framework asp.net-mvc-4


【解决方案1】:

这是因为 Answer 上的 AnswerId 属性不可为空

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

此外,EF 显然认为您将设置适当的 id。如果将 AnswerId 配置为标识列(自动递增 id),则 EF 不会抱怨。

【讨论】:

  • 我的数据还没有到 EF。它作为空值出现,由控制器方法接收,我在它到达 EF 之前对其进行检查。你提到不可为空。如何使该字段不可为空?谢谢。
  • 您通过添加“?”使该字段可以为空在类型之后:public int? AnswerId { 得到;放;但是,为什么你希望它为空?我认为让你的主键可以为空不是一个好主意......
  • 我正在使用实体框架,它是一个身份列。我认为我可以插入数据并让数据库创建一个值的唯一方法是它是否为空。如果您有任何想法,请告诉我。
  • 哦不,你错了。如果您使用 id '0' 保存记录并且该列被配置为一个身份,实体框架应该没有问题保存它并给它一个正确的 id。如果不起作用,您能否将完整的异常粘贴到 pastebin 或其他东西上?
  • 实际上,当我添加它并且有一个 0 时,我没有看到异常。它似乎根本没有添加它。我将尝试对此进行更多研究,然后进行更新。谢谢
猜你喜欢
  • 2016-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多