Wie kann ich EF hinzufügen mehrere untergeordnete Einheiten, um ein Objekt, wenn das Kind hat eine Identität-Taste?
Sind wir mit EF5 und SQL Server 2012 die folgenden zwei Klassen:
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; }
}
Zuordnung ist wie folgt:
public class AnswerMap : EntityTypeConfiguration<Answer>
{
public AnswerMap()
{
//Primary Key
this.HasKey(t => t.AnswerId);
//Identity
this.Property(t => t.AnswerId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Datenbank 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)
)";
Hier sind die Ergebnisse, was, die ich versucht habe:
Dies funktioniert bei einem Kind:
var a = new Answer{
Text = "AA",
QuestionId = 14
};
question.Answers.Add(a);
_uow.Questions.Update(question);
_uow.Commit();
Dies funktioniert nicht bei mehr als einem Kind:
Fehler: Ein Objekt mit demselben Schlüssel ist bereits vorhanden in der ObjectStateManager. Der ObjectStateManager nicht verfolgen können, mehrere Objekte mit dem gleichen Schlüssel.
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();
Dies funktioniert nicht bei mehr als einem Kind:
Schafft es AnswerID 's 1000 und 1001 aber ich möchte, dass neue Id' s erstellt werden, die von der Datenbank.
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();
Funktioniert nicht:
Compiler-Fehler. Kann nicht konvertieren 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();
Nicht funktioniert:
ObjectStateManager nicht verfolgen können, mehrere Objekte mit dem gleichen Schlüssel.
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 meiner Anwendung habe ich eine oder mehrere neue Antwort-Objekte auf dem client generiert und diese dann an den server gesendet werden. Oben bin ich simulieren, was passieren wird, ohne hinzufügen des client zu der Frage. Beachten Sie, dass die addition aller Antworten zu der Frage-Objekt auf dem client ausgeführt und dann kommt immer in einem JSON-string an den server. Es ist dann deserialisiert, um eine Frage Objekt wie folgt:
public HttpResponseMessage PutQuestion(int id, Question question) {
_uow.Questions.Update(question);
_uow.Commit();
Ich soll jede Antwort, die Objekte erstellt werden, die mit einem new identity ID
, für diese werden Hinzugefügt, um das Frage-Objekt und für das Frage-Objekt zurückgegeben werden, wieder in den normalen Weg.
Ich weiß nicht, wie dies getan werden kann. Alle meine tests bisher nicht funktioniert. Bitte beachten: dies ist eine variation auf eine frühere Frage von unserer Gruppe-Mitglied, das war weniger klar, und ich bin versucht zu schließen. Diese Frage ist, ich hoffe, dass mehr klar.
Hinweise:
Hier ist der Weg, update ist codiert:
public virtual void Update(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State == EntityState.Detached)
{
DbSet.Attach(entity);
}
dbEntityEntry.State = EntityState.Modified;
}
Syntax-Fehler - ist jetzt behoben. Vielen Dank für diesen Hinweis. Der eigentliche code versucht, hinzufügen ein "a" und dann "b" - variable.
InformationsquelleAutor | 2013-07-30
Du musst angemeldet sein, um einen Kommentar abzugeben.
Haben Sie erwähnt, dass Sie hinzufügen
a
zwei mal...?!In der Regel, um Elemente hinzuzufügen, die Ihre id ist die Identität, müssen Sie überspringen die Einstellung der id. Sie sollten auch hinzufügen, das
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
- Attribut, um diese IDs:Und fügen Sie Daten wie diese:
So fügen Sie Sie einfach so. Keine Notwendigkeit, zuerst fügen Sie Sie zu
Question
...Amin - Mein problem ist, dass alle Arbeit getan ist auf dem client. Die Antwort von Objekten Hinzugefügt werden, da auf die Frage-Objekt. Wenn der Benutzer auf speichern klickt diese an den server übergeben wird, als eine Frage Objekt komplett mit dem neuen Antworten. Ich hätte gedacht, dass EF in der Lage gewesen wären zu verwalten, das update von einer Frage mit neuer Antwort-Objekte. Vielleicht ist es nicht möglich, in EF, aber es scheint wie eine grundlegende Notwendigkeit.
wenn Sie möchten, aktualisieren Sie Sie, wie diese
_uow.Questions.Update(question);
müssen Sie alle alten und neuen Antworten auf die Frage und dann aktualisieren...Wenn Sie möchten, eine vollständige, zuverlässige und fehlerfreie Art und Weise, Sie haben mehrere Werke zu tun. Siehe dieser um Ihnen zu zeigen, wie. Ich habe auch einige Antworten zu diesem Bereich wie zum Beispiel dieser
InformationsquelleAutor AminSaghi
Ich habe laufen in die gleiche Identität "Einschränkung" als gut. Es stellt sich heraus, dass, wenn Sie ein Elternteil und alle Kinder, EF verarbeiten kann, die Tatsache, dass die Eltern und Kinder werden addiert. Sie laufen in Probleme, wenn Sie Aktualisieren Sie die Eltern und legen Sie zwei Kinder zur gleichen Zeit. Wenn Sie legen die Eltern, EF wird automatisch Holen, diese zwei Kinder, und befestigen Sie Sie, ob Sie es wollen oder nicht. Da wir wollen, dass es automatische generieren der Id, würden wir nicht setzen Sie den Primärschlüssel der Kinder. Aber EF nicht in den Griff Elemente mit den gleichen Primärschlüssel haben, wenn der andere Elternteil ist, ein Update und bläst, da beide den gleichen PK 0 für beide Kinder.
Die einzige Möglichkeit, die ich gefunden habe, um dieses ist, um manuell die ids von den Kindern zu unterschiedlichen zahlen. Ich in der Regel das erste child-Id in -1 dann -2 für das zweite Kind, und so weiter. Dadurch wird EF den Kindern zu retten und die Schlüssel werden automatisch durch das Identity-Ausführung auf der Datenbank, da -1 und -2 sind nicht gültig identity-Werte.
Wird dies jedoch große Schmerzen verursachen, wenn Sie eine 3rd-level oder darüber hinaus. Nicht nur, dass Sie auf die Aktualisierung dieser PK auf jedes Kind, aber dann hätten Sie zur Aktualisierung der FK auf jedem Ihrer Kinder an diese neue -1 oder -2 Wert sind. Ansonsten, das speichern wird wieder scheitern!
Die einzige andere Möglichkeit die ich sehe ist wirklich nur das einfügen eines Kindes zu einem Zeitpunkt, und nennen Sie den Kontext, nicht den Umgang mit mehr als ein Objekt mit dem gleichen PK, aber diese Art von Niederlagen der Zweck der ein ORM...
Als der EF 6.1.2 (vielleicht früher), ist dies kein problem mehr. Es scheint zu funktionieren wie erwartet, jetzt! 🙂
Eigentlich, wenn Sie ausführen, durch das entity-Baumes und fügen Sie alle neuen Objekte aus, bevor Sie die updates, es funktioniert gut, auch.
Ich weiß, dieser thread ist fast drei Jahre alt, aber ich wollte nur sagen, dass ich ' ve begegnet das gleiche problem wie @DanielLorenz beschrieben, während mit EF 6.1.3. Die einzige Möglichkeit die ich habe um ihn herum ist, indem Sie ein Kind in einer Zeit,
Eine andere Lösung ist nur Fügen Sie alle neuen Objekte zuerst. Sobald alle Adds erledigt sind, können Sie gehen Sie zurück und fügen Sie alle anderen Elemente danach. Dies ist, was ich am Ende tun, um zu vermeiden, die Zuweisung von negativen PKs die ganze Zeit.
InformationsquelleAutor Daniel Lorenz
Versuchen Sie, diese Dinge:
Create()
Methode derDbSet
Answers
Sammlung IhrerContext
Gesetzt
QuestionId
passend für EF zu realisieren, die Beziehung. Auch, nicht explizit festgelegt AnswerId auf null.Müssen Sie möglicherweise einen Anruf zu tätigen, um
_uow.ChangeTracker.DetectChanges()
wenn Sie plan auf das Abfragen derAnswers
Sammlung vonQuestion
14InformationsquelleAutor qujck
Wenn Sie richtig deklariert die Id als Schlüssel und als DBGenerated Identität.
Dann EF wird Ihnen erlauben, HINZUFÜGEN viele von diesen auf den Kontext, vor dem speichern.
Sie können NICHT an Elemente mit dem gleichen Schlüssel.
Befestigen Sie gedacht, für den offline-Daten, in einen Zusammenhang setzen, setzen Sie seinen Status und speichern von Szenarien.
Sie haben entweder die Gleiche Instanz zweimal und mit EF-tracking standardmäßig verursacht ein Chaos.
Oder irgendwie verwendet, BEFESTIGEN zweimal. Stellen Sie sicher, dass Sie den Umgang mit Ihren Instanzen sauber.*
zB
Einer nur versucht, einen einfachen Test zu überprüfen, es funktioniert (ef5)
edit: Auf Anfrage, hinzufügen, speichern-Respository heruntergeladen-Muster, BAsic-Beispiel, Fehlerbehandlung entfernt
....
vereinbart das snippet sieht ok wieder neue Instanzen. Wenn das wirklich der code. was bedeutet _uow.Fragen.Update(Frage);? Ich nehme an auch verpflichten nur Anrufe SAveChanges. Der einzige offensichtliche Unterschied ist ich benutze IMMER virtual auf POCO-Requisiten
Update enthält das folgende: public virtual void Update(T entity) { DbEntityEntry dbEntityEntry = DbContext.Entry(entity); if (dbEntityEntry.State == EntityState.Detached) { DbSet.Attach(entity); } dbEntityEntry.State = EntityState.Modifiziert; } Sorry wegen der Darstellung in diesem Kommentar-Bereich. Ja commit nicht savechanges aufrufen. Die POCO-Eigenschaft sind Sie zu beziehen. Ich dachte, alle diejenigen, die es benötigt, wurden als virtual deklariert in meinem code.
gibt es das problem... legen Sie nicht befestigen Sie den selben key zweimal. ill update beantworten zu betonen, Punkt
Danke Phil. Ich habe meine update-code der Frage. Gibt es einige andere generische update, das ich hinzufügen könnte, um das repo zu verwenden? Wenn Sie eine Antwort könnte Ihnen einen Vorschlag machen, wie ich konnte recode Dank.
InformationsquelleAutor phil soady