如何使用EF将多个子实体加入到当孩子有标识键的对象? [英] How can I use EF to add multiple child entities to an object when the child has an identity key?

查看:94
本文介绍了如何使用EF将多个子实体加入到当孩子有标识键的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 公共类问题
{
    公众质疑()
    {
        this.Answers =新的List<应答和GT;();
    }
    公众诠释QuestionId {搞定;组; }
    公共字符串名称{搞定;组; }
    公共虚拟的ICollection<应答和GT;答案{搞定;组; }}
公共类答
{
    公众诠释AnswerId {搞定;组; }
    公共字符串文本{搞定;组; }
    公众诠释QuestionId {搞定;组; }
    公共虚拟问题问题{搞定;组; }
}

映射如下所示:

 公共类AnswerMap:EntityTypeConfiguration<应答和GT;
{
    公共AnswerMap()
    {
        // 首要的关键
        this.HasKey(T => t.AnswerId);        //身份
        this.Property(T => t.AnswerId)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

数据库DDL

  CREATE TABLE答案(
    [AnswerId] INT IDENTITY(1,1)NOT NULL,
    [QuestionId] INT NOT NULL,
    【正文】NVARCHAR(1000)
    约束[PK_Answer] PRIMARY KEY CLUSTERED([AnswerId] ASC)
);

下面是我所试过的结果:

本工程为一个孩子:

  VAR一个=新的答案{
    文本=AA,
    QuestionId = 14
};
question.Answers.Add(一);
_uow.Questions.Update(问题);
_uow.Commit();

这不会超过一个孩子的工作:

错误:具有相同键的对象已经存在于ObjectStateManager。该ObjectStateManager无法跟踪多个对象使用相同的密钥。

  VAR一个=新的答案{
    AnswerId = 0,
    文本=AAA,
    QuestionId = 14
};
变种B =新的答案{
    AnswerId = 0,
    文本=BBB,
    QuestionId = 14
};
question.Answers.Add(一);
question.Answers.Add(二);
_uow.Questions.Update(问题);
_uow.Commit();

这不会超过一个孩子的工作:

它创建AnswerID的1000和1001,但我想新的I​​D的由数据库中创建。

  VAR一个=新的答案{
    AnswerId = 1000,
    文本=AAA,
    QuestionId = 14
};
变种B =新的答案{
    AnswerId = 1001,
    文本=BBB,
    QuestionId = 14
};
question.Answers.Add(一);
question.Answers.Add(二);
_uow.Questions.Update(问题);
_uow.Commit();

不起作用:

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

  VAR一个=新的答案{
    AnswerId = NULL,
    文本=AAA,
    QuestionId = 14
};
变种B =新的答案
{
    AnswerId = NULL,
    文本=BBB,
    QuestionId = 14
};
question.Answers.Add(一);
question.Answers.Add(二);
_uow.Questions.Update(问题);
_uow.Commit();

不起作用:

ObjectStateManager无法跟踪多个对象使用相同的密钥。

  VAR一个=新的答案{
    文本=AAA,
    QuestionId = 14
};
变种B =新的答案
{
    文本=BBB,
    QuestionId = 14
};
question.Answers.Add(一);
question.Answers.Add(二);
_uow.Questions.Update(问题);
_uow.Commit();

在我的应用程序在客户端上生成一个或多个新应答的对象,然后将这些被发送到服务器。上面的我模拟会发生什么不添加到客户端的问题。请注意,所有问题的答案对象的加入在客户端上完成,然后过来一个JSON字符串到服务器。然后,它进行反序列化到一个问题对象是这样的:

 公开的Htt presponseMessage PutQuestion(INT ID,问问题){
            _uow.Questions.Update(问题);
            _uow.Commit();

欲与新标识ID ,对于这些被添加到问题的对象,并为课题对象在被返回背面创建的每个回答对象正常的方式。

我不知道如何可以做到这一点。我所有的简单测试至今没有工作。请注意,这是我们组成员先前的问题这是不太清楚,哪些我试图关闭的变化。这个问题是我希望更清晰。

注:

下面是更新的方式codeD:

 公共虚拟无效更新(T实体)
{
    DbEntityEntry dbEntityEntry = DbContext.Entry(实体);
    如果(dbEntityEntry.State == EntityState.Detached)
    {
        DbSet.Attach(实体);
    }
    dbEntityEntry.State = EntityState.Modified;
}


解决方案

你提到要添加 A 两次......?!

  question.Answers.Add(一);
question.Answers.Add(一);

一般情况下,增加的项目,他们的id是身份,你必须跳过设置id。您还应该添加 [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 属性,这些ID:

 公共类答案
{
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)
    公众诠释AnswerId {搞定;组; }
    公共字符串文本{搞定;组; }
    公众诠释QuestionId {搞定;组; }
    公共虚拟问题问题{搞定;组; }
}

和添加这样的数据:

  VAR一个=新的答案{
    文本=AAA,
    QuestionId = 14
};变种B =新的答案
{
    文本=BBB,
    QuestionId = 14
};dbContext.Answers.Add(一);
dbContext.Answers.Add(二);dbContext.SaveChanges();// ...

We are using EF5 and SQL Server 2012 the following two classes:

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

Mapping is as follows:

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

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

Database 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)
)";

Here are the results of what I have tried:

This works for one child:

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

This does not work for more than one child:

Error: An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.

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

This does not work for more than one child:

It creates AnswerID's 1000 and 1001 but I want new Id's to be created by the database.

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

Does not work:

Compiler error. Can't convert null to 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();

Doesn't work:

ObjectStateManager cannot track multiple objects with the same key.

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

In my application I have one or more new Answer objects generated on the client and then these are sent to the server. Above I am simulating what will happen without adding the client into the question. Note that the adding of all Answers to the Question object is done on the client and then comes over in a JSON string to the server. It is then deserialized to a Question Object like this:

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

I want each Answer objects to be created with a new identity ID, for these to be added to the Question object and for the Question object to be returned back in the normal way.

I don't know how this can be done. All my simple tests so far don't work. Please note this is a variation on an earlier question by our group member which was less clear and which I am trying to close. This question is I hope more clear.

Notes:

Here is the way update is coded:

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

解决方案

Did you mentioned that you are adding a two times...?!

question.Answers.Add(a);
question.Answers.Add(a);

Usually, to add items which their id is identity, you must skip setting the id. You also should add the [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] attribute to these IDs:

public class Answer
{
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int AnswerId { get; set; }
    public string Text { get; set; }
    public int QuestionId { get; set; }
    public virtual Question Question { get; set; }
}

And add data like this:

var a = new Answer{
    Text = "AAA",
    QuestionId = 14
};

var b = new Answer
{
    Text = "BBB",
    QuestionId = 14
};

dbContext.Answers.Add(a);
dbContext.Answers.Add(b);

dbContext.SaveChanges();

// ...

这篇关于如何使用EF将多个子实体加入到当孩子有标识键的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆