Einfügen von Primärschlüsselwerte mit SubSonic und SQLite - Problem, weil SubSonic denkt Spalten sind entweder AutoIncrement oder nicht

StackOverflow https://stackoverflow.com/questions/2283063

Frage

Ich bin mit SubSonic 2.2 und SQLite und haben ein Problem festgestellt, wenn sie mit Tabellen mit einer INTEGER PRIMARY KEY-Spalte handelt, die nicht AUTOINCREMENT ist. Nach dem faq :

  

Wenn Sie eine Spalte einer Tabelle deklarieren INTEGER PRIMARY KEY zu sein, dann, wenn Sie eine NULL in dieser Spalte der Tabelle einfügen, wird die NULL automatisch in eine ganze Zahl umgewandelt, die über eine größer als der größte Wert in dieser Spalte alle anderen Zeilen in der Tabelle, oder 1, wenn die Tabelle leer ist.

denkt also SQLite diese Spalten sind manchmal Auto erhöht (dh nur wenn NULL-Werte vorhanden sind). Das Problem ist, dass SubSonic denkt, sie sind immer Auto erhöht.

In meiner Anwendung meines ID-Wert von einer entfernten Datenbank generiert werden, so will ich nicht zu automatisch zu generieren sie in SQLite. Dies sollte kein Problem sein: Ich werde einfach Wert liefern, wenn ich Datensätze in dieser Tabelle erstellen. Allerdings, wenn ich SubSonic der sonic.exe zu automatisch generieren meine DAL verwenden, wird die Primärschlüsselspalte auf AutoIncrement gesetzt = true. Dies scheint zu bedeuten, dass ich nicht die ID-Spalte festlegen -. Unterschall des ActiveHelper.GetInsertCommand () ignoriert, da sie es den automatisch generierten denkt

Die Linie, wo es ob autoincrement es das bestimmt, oder nicht in SubSonic.SQLiteDataProvider.GetTableSchema ist ():

column.AutoIncrement = Convert.ToBoolean(row["PRIMARY_KEY"]) && GetDbType(row["DATA_TYPE"].ToString()) == DbType.Int64;

Ich denke, die Lösung entweder auf

  • Nicht INTEGER PRIMARY KEY Spalte für Schlüssel verwenden, die an anderer Stelle erzeugt werden, oder

  • Ändern Sie die Vorlagen so diese Art von Spalten sind nicht auf AutoIncrement = true gesetzt. Dies würde bedeuten, SubSonic wird nicht immer, sie als Autoinkrement behandeln, so dass ich vorsichtig sein, würde, dass ich später nicht erwarten, dass automatisch generierten Werte zu erhalten. Ich glaube nicht, es ist möglich, innerhalb der Templates wurden leider leicht feststellen, ob die Spalte wirklich AUTOINCREMENT ist oder nicht, so würde ich vielleicht einige hässliche Hartcodierung statt zu tun haben ....

Jede andere Gedanken oder Anregungen?

War es hilfreich?

Lösung

Leider sieht es aus wie unsere SQLiteDataProvider, dass davon ausgegangen, wenn es eine Int64 PK, dann ist es die Auto-Inkrement. Ich suche die Quelle jetzt über (ich habe nicht diesen Anbieter schreiben) und ich kann sehen, dass die Art und Weise das Schema geladen wird, wird Connection.GetSchema mit - der System.Data.Common.DbConnection gebaut verwendet das Schema zu erhalten für die Tabellen.

Dies ist suboptimal die meiste Zeit, weil es nur begrenzte Informationen zurückgibt. In diesem Fall - es sagt uns nicht, wenn die Spalte AUTOINCREMENT ist oder nicht. Wahrscheinlich gibt es einen besseren Weg, SQLite die Meta-Informationen auf dem Tisch zu stellen -. Aber es war leider nicht verwendet

Kurze Antwort:. Definieren eine neue PK, wenn Sie können, und mit der anderen Schlüssel als Referenz

Andere Tipps

Wie ich bereits erwähnt, bevor ich in einem überarbeiteten SQLiteDataProvider im Dezember geprüft. Überprüfen Sie, ob an der Linie 407 in SQLiteDataProvider.cs Sie haben:

// Autoincrement Erkennung jetzt auch in der letzten System.Data.SQLite. 1.0.60.0 - paul Column.AutoIncrement = Convert.ToBoolean (row [ "AUTOINCREMENT"]);

Es gibt auch mehrere andere Verbesserungen und Fehlerbehebungen in den umliegenden Linien. Der neue Code wurde nie in Github Ich denke, in das Hauptprojekt Verteilung hinzugefügt, verstehe ich nicht, das Projekt zu viel. SQLite ist ein wunderbarer Anbieter gewesen, abgesehen von der Dateiebene Verriegelung. Ich habe eine home grown-Version System.Data.SQLite, die den neuen Fremdschlüssel verwendet von SQLite verfügt, und die offizielle Version sollte in diesem Monat geschehen?

Hier ist die überarbeitete Fassung: SQLiteDataProvider.cs

BTW, lesen Sie in diesem Projekt den Fall, dass Sie konvertieren von SQL Server:

Konvertieren SQL Server DB zu SQLite DB http://www.codeproject.com/KB/database/convsqlservertosqlite.aspx

Ich finde ich keine Create geschrieben, wie in SqlDataProvider wegen der Dateisperrung verwenden kann. Die Create in SQLiteDataProvider wie es jetzt ist, ist falsch, da es neue Verbindungszeichenfolgen ignoriert.

Die System.Data.SQLite doc sagt: „Sie mehrere Threads erstellen können und diese Fäden können ihre eigenen SQLiteConnection und nachfolgende Objekte erstellen für Zugriff auf eine Datenbank. Mehrere Verbindungen auf mehreren Threads zu der gleichen Datenbankdatei durchaus akzeptabel sind und verhalten vorhersagbar. "

Also, was ich versucht habe, ist die folgende, und es ist wirklich cludgey. Verwenden Sie ein Wörterbuch von Verbindungen durch Thread-ID und Verbindungszeichenfolge eingegeben. Aber alle Einheitstests bestehen, darunter die meisten der Transaktionen (braucht bessere Tests). Ich schrieb Tests ein paar mehr Transaktion, mit kritischem Abschnitt Schlössern, und ich denke, es ist Thread-sicher sein könnte, nur realistischere Tests benötigen.

private Dictionary<string, SQLiteConnection> threadConnectionTable = new Dictionary<string, SQLiteConnection>();

public override DbConnection CreateConnection(string newConnectionString)
{
    SQLiteConnection conn;
    string connKey = "t" + Thread.CurrentThread.ManagedThreadId + "__" + newConnectionString;
    if(threadConnectionTable.ContainsKey(connKey))
    {
        conn = threadConnectionTable[connKey];
        if(conn.State != ConnectionState.Open)
            conn.Open();
        return conn;
    }
    conn = new SQLiteConnection(newConnectionString);
    conn.Open();
    threadConnectionTable[connKey] = conn;
    return conn;
}



private Object thisLock = new Object();

[Test]
[ThreadedRepeat(10)]
public void MultiThreadRepeat()
{
    lock(thisLock)
    {
        var qcc = new QueryCommandCollection();
        int threadId = Thread.CurrentThread.ManagedThreadId;
        Debug.WriteLine("MultiThreadRepeat: thread id = " + threadId);
        int count = 0;
        for(int n = 0; n < 10; n++)
        {
            Query qry1 = new Query(Product.Schema);
            qry1.QueryType = QueryType.Update;
            qry1.AddWhere(Product.Columns.ProductID, n);
            qry1.AddUpdateSetting("ProductName", threadId + ": unit test ");
            QueryCommand cmd = qry1.BuildUpdateCommand();
            qcc.Add(cmd);
            count++;
        }
        DataService.ExecuteTransaction(qcc);
        var p1 = new Product(1);
        Assert.AreEqual(p1.ProductName, threadId + ": unit test ", StringComparison.InvariantCultureIgnoreCase);
    }

}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top