2009-08-11 12 views
0

Ich bin mit LINQ, aber meine Datenbank-Tabellen nicht über eine Identity-Spalte (obwohl sie eine Leihmutter Primary Key-ID-Spalte verwenden)LINQ Inserts ohne Identity-Spalte

Kann das funktionieren?

Um die Identitätswerte für eine Tabelle abzurufen, gibt es eine gespeicherte Prozedur namens GetIDValueForOrangeTable(), die eine SystemValues-Tabelle betrachtet und die ID darin inkrementiert. Gibt es eine Möglichkeit, wie ich LINQ erhalten kann, um den ID-Wert aus dieser SystemValues-Tabelle auf einer Einfügung zu erhalten, anstatt die integrierte IDENTITY?

Nebenbei, ich denke nicht, dass dies eine sehr gute Idee ist, vor allem nicht für eine Webanwendung. Ich stelle mir vor, dass es wegen dieser SystemValues-Suche viele Parallelkonflikte geben wird. Bin ich in meiner Sorge gerechtfertigt?

Prost Duncan

Antwort

1

Sicher, dass Sie diese Arbeit mit LINQ machen, und sicher auch:

  • wickeln Sie den Zugriff auf die Tabelle zugrunde liegenden SystemValues ​​in der „GetIDValue .....() "Funktion in einer TRANSACTION (und nicht mit der READUNCOMMITTED Isolationsstufe!), dann kann ein und nur ein Benutzer jederzeit auf diese Tabelle zugreifen und Sie sollten ID
  • aufrufen können, die Proc von LINQ direkt zuvor gespeichert Speichern Sie Ihre Entität und speichern Sie die ID, wenn Sie mit einer neuen Entität zu tun haben (Wenn die ID wurde noch nicht festgelegt)
  • speichern Ihre Einheit in der Datenbank

, die funktionieren sollte - nicht sicher, ob es schneller ist und mehr effizienter als lassen die Datenbank die Arbeit tun - aber es sollte funktionieren - und sicher.

Marc

UPDATE:

So etwas wie diese (an Ihre Bedürfnisse anpassen) wird sicher arbeiten:

CREATE PROCEDURE dbo.GetNextTableID(@TableID INT OUTPUT) 
AS BEGIN 
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED 

    BEGIN TRANSACTION 

    UPDATE SystemTables 
    SET MaxTableID = MaxTableID + 1 
    WHERE ........ 

    SELECT 
     @TableID = MaxTableID 
    FROM  
     dbo.SystemTables 

    COMMIT TRANSACTION 
END 

Was die Leistung - solange Sie eine angemessene Anzahl (weniger als 50 vielleicht) der gleichzeitigen Benutzer, und solange diese Tabellen nicht für viel mehr verwendet wird, sollte es OK durchführen.

+0

Wird dies unter einer Web-App sicher (und angemessene Leistung) sein? Die einzige gültige Transaktionsebene für das Web ist das Optimistische Sperren, nicht wahr? Korrigiere mich, wenn ich falsch liege! – Duncan

+0

Vielen Dank, wirklich geschätzt und werde es ein paar Gedanken machen. Wir könnten jedoch tausende, wenn nicht Millionen von Benutzern haben, die diese Datenbank in kurzer Zeit erreichen, also müssen wir ernsthaft über die Leistung nachdenken! – Duncan

+1

Sie können dies tun, ohne zweimal auf 'SystemTables' zuzugreifen - wie in der zweiten Methode [in dieser Antwort] (http: // stackoverflow.com/questions/3453411/sql-server-auto-inkrementierung-das-erlaubt-update-statements/3462957 # 3462957) –

1

Sie sind sehr berechtigt in Ihrem Interesse. Wenn zwei Benutzer versuchen, zur selben Zeit einzufügen, erhalten beide die gleiche Nummer, es sei denn, Sie tun wie von marc_s beschrieben und fügen das Ding in eine Transaktion ein. Wenn die Transaktion jedoch nicht die gesamte Einfügung sowie die Tabelle mit den ID-Werten umschließt, können beim Schließen der äußeren Einfügung immer noch Lücken vorhanden sein (er hat einen Wert, aber aus einem anderen Grund wurde keine eingefügt) Aufzeichnung). Da die meisten Menschen dies tun, um Lücken zu vermeiden (was in den meisten Fällen eine unnötige Anforderung ist), macht sie das Leben komplizierter und kann das Ergebnis möglicherweise nicht erreichen. Die Verwendung eines Identitätsfeldes ist fast immer eine bessere Wahl.