Ist es möglich, den Identity Field-Wert zu erhalten, bevor er im Entity-Framework gespeichert wird

Ich habe einen Kunden und Verkaufstisch

CUSTOMER -------------- Id (int auto increment) Name SALES --------------- Id (int auto increment) CustomerId (int) OrderTotal (decimal) 

Mit Guid kann ich das machen.

 dbTransaction = dbContext.Database.BeginTransaction(isolationLevel); var customer = new Customer() { Id = Guid.NewGuid(), Name = "John Doe" }; var sales = new Sales() { Id = Guid.NewGuid(), CustomerId = customer.Id, OrderTotal = 500 }; dbContext.SaveChanges(); dbTransaction.Commit(); 

Wie kann ich das tun, wenn mein Primärschlüssel int ist (mit DatabaseGeneratedOption.Identity)?

Solutions Collecting From Web of "Ist es möglich, den Identity Field-Wert zu erhalten, bevor er im Entity-Framework gespeichert wird"

Du kannst nicht. Die ID, die in eine IDENTITY Spalte geht, wird von der database beim Einfügen erzeugt und alle "Tricks", um das zu umgehen und die ID selbst zu bestimmen, sind wahrscheinlich errorshaft.

Kurze Antwort: Wenn du bei der UNIQUEIDENTIFIER einer ID sagen willst, kannst du eine GUID ( UNIQUEIDENTIFIER ) oder eine SEQUENCE (wenn du mit SQL server 2012 oder neuer UNIQUEIDENTIFIER ).

Warum solltest du nicht die nächste freie ID selbst berechnen:

Denken Sie nicht einmal an Tricks wie das Ausführen einer Abfrage wie context.Customers.Max(c => c.Id) + 1 , da es immer die Möglichkeit gibt, dass Sie gleichzeitige databasezugriffe haben: ein anderer process oder Thread kann eine neue Entität bestehen bleiben auf die gleiche Tabelle, nachdem Sie die nächste "freie" ID gelesen haben, aber bevor Sie Ihre Entität speichern. Die Berechnung der nächsten freien ID wird anfällig für Kollisionen sein, es sei denn, Ihr ganzer Vorgang, die ID zu bekommen, etwas dabei zu machen und die Entität mit dieser ID zu speichern, war atomar. Dies würde wahrscheinlich eine Tabellensperre in der DB erfordern, was ineffizient sein könnte.

(Das gleiche Problem existiert auch wenn du SEQUENCE s SEQUENCE , ein neues Feature, das in SQL server 2012 eingeführt wurde.) ( Ich war falsch , siehe Ende der Antwort).

Mögliche Lösungen:

  1. Wenn Sie die ID eines objects bestimmen müssen, bevor Sie es speichern, dann verwenden Sie nicht die ID, die in einer IDENTITY Spalte geht. Bleiben Sie mit einer GUID , weil Sie extrem unwahrscheinlich sind, um eine Kollision mit diesen zu bekommen.

  2. Es gibt keine Notwendigkeit, zwischen dem einen oder anderen zu wählen: Sie können tatsächlich Ihren Kuchen haben und es essen! Nichts hält Sie davon ab, zwei ID-Spalten zu haben , eine, die Sie extern bestimmen (die GUID) und eine, die intern in der DB bleibt (die IDENTITY Spalte); sehen Sie den Blog-Artikel "CQS vs. server generierte IDs" von Mark Seemann für einen genaueren Blick auf diese Idee. Hier ist die allgemeine Idee von Beispiel:

     CREATE TABLE Foos ( FooId INT IDENTITY NOT NULL PRIMARY KEY CLUSTERED, -- ^^^^^ assigned by the DBMS upon insertion. Mostly for DB-internal use. Id UNIQUEIDENTIFIER ROWGUIDCOL NOT NULL UNIQUE DEFAULT (NEWID()), -- ^^ can be dictated and seen by the users of your DB. Mostly for DB-external use. … ); CREATE TABLE FooBars ( FooId INT NOT NULL FOREIGN KEY REFERENCES Foos (FooId), -- use DB-internal ID in foreign key constraints ^^^^^ … ); CREATE VIEW PublicFoos AS SELECT Id, … FROM Foos; -- ^^ publish the public ID for users of your DB 

    (Vergewissern Sie sich, dass Sie eine Konvention zur konsequenten Benennung von internen und öffentlichen ID-Feldnamen einhalten.)

  3. SEQUENCE s , ein Feature, das in SQL server 2012 eingeführt wird, sind eine mögliche Alternative zu einer IDENTITY Spalte. Sie werden automatisch erhöht und Sie erhalten eine eindeutige Nummer, wenn Sie die nächste freie ID mit NEXT VALUE FOR SomeSequence . Einer der auf MSDN genannten Anwendungsfälle sind:

    Verwenden Sie Sequenzen anstelle von Identitätsspalten in den folgenden Szenarien: […] Die Anwendung erfordert eine Nummer, bevor die Einfügung in die Tabelle erfolgt ist.

    Einige Einschränkungen:

    • Wenn Sie den nächsten Sequenzwert erhalten, benötigen Sie einen zusätzlichen Rundgang in die database.

    • Wie Identitätsspalten können Sequenzen zurückgesetzt oder wiederhergestellt werden, also gibt es die theoretische Möglichkeit von ID-Kollisionen. Am besten, um niemals Identitätsspalten und Sequenzen wieder zu sehen, wenn ihr es helfen könnt.

    • Wenn Sie den nächsten freien Sequenzwert mit NEXT VALUE FOR , aber dann entscheiden, nicht zu verwenden, wird dies zu einer "Lücke" in Ihren IDs führen. Lücken können offensichtlich nicht mit regelmäßigen (nicht sequentiellen) GUIDs passieren, da es keine inhärente Bestellung gibt.

Soweit ich weiß, können Sie die ID nicht erhalten, bevor Sie die Änderungen in der database speichern. Die database erstellt die ID, nachdem die Werte in die database eingefügt wurden.

Um es hinzuzufügen, wenn Sie .SaveChanges() anrufen, dann wird nur die Änderungen an der database geschrieben und erst dann wird der Identitätswert generiert.

Sie können diesen Wert durch einen kleinen Hack bekommen.

Erstellen Sie eine function in SQL server so etwas wie dies

 CREATE FUNCTION fn_getIdentity(@tbl_name varchar(30)) AS BEGIN IF @tbl_name = 'Employee_tbl' RETURN IDENT_CURRENT('Employee_tbl') ELSE IF @tbl_name = 'Department_tbl' RETURN IDENT_CURRENT('Department_tbl') ELSE RETURN NULL END 

Erstellen Sie eine Entität in Ihrem Entity-Framework, um diese function zu unterstützen und verwenden Sie es, wohin Sie wollen.

Dann benutze

 var nextValue = dbContext.fn_getIdentity("Employee_tbl") 

IDENT_CURRENT gibt Ihnen den letzten inkrementierten Wert für eine Identitätsspalte zurück. Dies bedeutet nicht MAX + 1, als ob Ihre vorherige Transaktion einen Identitätswert für diese Spalte erzeugt hat, aber wurde zurückgesetzt, dann sehen Sie den nächsten Wert, der generiert wird.

Bitte beachten Sie, ich habe die Syntax nicht richtig überprüft und diese Syntax ist nur eine Idee zu präsentieren.

Allerdings würde ich mit der Lösung von Stakx dh SEQUENCE, wenn mit SQL server 2012 oder oben noch eine Tabelle zur Implementierung der functionalität von SEQUENCE durch die Reservierung ID einmal einmal dauerhaft in einer Tabelle erstellt implementiert.