2016-05-23 9 views
3

Ich verwende Dapper mit C# und Back-End ist MS Access. Meine DAL-Methode fügt Datensatz in Datenbank ein. Ich möchte einen eindeutigen Bezeichner (oder aktualisierten POCO mit eindeutiger Kennung) der eingefügten Zeile zurückgeben. ich meine Funktion etwas erwartet wie folgt (Ich weiß, das funktioniert nicht, nur zu erklären, was ich will): -Dapper + MSAccess: Wie bekomme ich die Kennung der eingefügten Zeile?

public MyPoco Insert(MyPoco myPoco) 
{ 
    sql = @"INSERT INTO MyTable (Field1, Field2) VALUES (@Field1, @Field2)"; 
    var param = GetMappedParams(myPoco);//ID property here is null. 
    var result = _connection.Query<MyPoco>(sql, param, null, false, null, CommandType.Text);.Single(); 
    return result;//This result now contains ID that is created by database. 
} 

Ich bin von NHibernate Welt und POCO aktualisiert automatisch mit NH. Wenn nicht; Wir können die Refresh-Methode aufrufen und die ID aktualisieren. Mir ist nicht bewusst, wie das mit Dapper zu erreichen ist.

Ich lese this Frage zu SO, die nicht relevant ist, da es über SQL Server spricht.

Eine andere this Frage hat keine Antwort angenommen.

Ich lese this Frage, wo akzeptiert Antwort erklärt Grubenstürze der Verwendung @@Identity.

+1

Ich denke, es ist Ihre Antwort http://StackOverflow.com/Questions/2230719/Scope-Identity-in-Microsoft-Access – progpow

+0

@Progpow: Sie vorschlagen ** SELECT @@ Identität **. Ich bin mir nicht sicher, ob das zuverlässig ist. Meine Anwendung ist eine Mehrbenutzeranwendung, in der mehrere Benutzer gleichzeitig Datensätze in derselben Tabelle einfügen. Nach meinem Verständnis wird dies nicht empfohlen. Korrigiere mich, wenn ich falsch liege. –

+0

Sie können testen, ich habe eine Antwort darauf geschrieben, kann sie aber nicht finden. Verwenden Sie eine isolierte Instanz (set db = currentdb), pausieren Sie vor dem SQL und fügen Sie einen Datensatz manuell ein. Ich denke, Sie werden feststellen, dass es wahr ist. – Fionnuala

Antwort

2

Dies ist, was für mich funktioniert:

static MyPoco Insert(MyPoco myPoco) 
{ 
    string sql = "INSERT INTO MyTable (Field1, Field2) VALUES (@Field1, @Field2)"; 
    _connection.Execute(sql, new {myPoco.Field1, myPoco.Field2}); 
    myPoco.ID = _connection.Query<int>("SELECT @@IDENTITY").Single(); 
    return myPoco; // This result now contains ID that is created by database. 
} 

Beachten Sie, dass dies mit einem OleDbConnection zu der Access-Datenbank arbeiten, aber es wird nicht Arbeit mit einem OdbcConnection.

bearbeiten re: Kommentar

Um sicherzustellen, dass die Verbindung zwischen dem Einsatz und der SELECT-Anrufe offen bleibt, könnten wir dies tun:

static void Insert(MyPoco myPoco) 
{ 
    string sql = "INSERT INTO MyTable (Field1, Field2) VALUES (@Field1, @Field2)"; 
    bool connAlreadyOpen = (_connection.State == System.Data.ConnectionState.Open); 
    if (!connAlreadyOpen) 
    { 
     _connection.Open(); 
    } 
    _connection.Execute(sql, new {myPoco.Field1, myPoco.Field2}); 
    myPoco.ID = _connection.Query<int>("SELECT @@IDENTITY").Single(); 
    if (!connAlreadyOpen) 
    { 
     _connection.Close(); 
    } 
    return; // (myPoco now contains ID that is created by database.) 
} 
+0

Dies funktioniert, solange '_connection' explizit geöffnet wird ** BEFORE **' INSERT INTO' und geschlossen ** AFTER ** 'SELECT @@ IDENTITY' Aufruf. Ich habe die Verbindung nicht richtig gehandhabt. Auch muss man verstehen, dass man '' @ Identity'' benutzt; Ich habe einen Link in meiner Frage angegeben. –

1

Nur ein paar zusätzliche Gedanken: Wenn die @@Identity pitfalls sind ein Problem, dann wäre eine andere Option, eine neue GUID im Code vorher zu erstellen und dann diese GUID mit dem Rest der Daten einzufügen, anstatt Access den Identitätswert beim Erstellen des neuen Datensatzes erstellen zu lassen.

Ich schätze, dass funktioniert nur, wenn Ihre besondere Situation einen GUID-Primärschlüssel für die Tabelle ermöglicht, aber es garantiert Ihnen, dass Sie den wahren Wert des Schlüssels für den Datensatz kennen, den Sie gerade eingefügt haben.

Wenn Sie keinen GUID-Schlüssel möchten, können Sie alternativ eine Tabelle mit einer einzelnen Zeile erstellen, die den aktuellen Ausgangswert für manuell verwaltete Schlüssel in Ihrer Anwendung enthält. Sie können dann den Wert des jeweiligen Startwerts jedes Mal manuell erhöhen, wenn Sie einen neuen Datensatz einfügen möchten. Wie beim GUID-Ansatz würden Sie die ID dann manuell in den Datensatz einfügen. Dieses Mal wäre die ID der neu inkrementierte Seed, den Sie gerade abgerufen haben.

Auch dies sollte Ihnen einen eindeutigen Schlüssel für jede Einfügung garantieren, obwohl Sie jetzt einen Lese- und zwei Schreibvorgänge für jede Einfügung durchführen.

+0

Guid ist eine gute Alternative, aber viele werden wegen seiner Größe und Leistung Penelity wegziehen. Das Hauptziel bestand darin, eine Datenreplikationsbeschwerde zu stellen. Möglicherweise hat Microsoft es deshalb "Autonumber" - "Replikations-ID" genannt. Ich denke, es gibt sehr wenige Entwickler, die diesen Datentyp mit MS Access verwenden. –

+0

Andere Alternative, die Sie vorgeschlagen haben (ID im Code zu generieren), sieht besser aus. Nachteil wie gesagt sind zusätzliche Datenbankaufrufe. Diese könnten leicht vermieden werden, indem ein Algorithmus verwendet wird, der keine DB verwendet. –

Verwandte Themen