2015-07-28 23 views
5

Sto utilizzando SQLite e System.Data.Linq.Mapping. Sto riscontrando un problema con il campo AUTOINCREMENT quando si utilizza l'attributo di mappatura linq IsDbGenerated = true.Errore nell'uso di System.Data.Linq.Mapping e incremento automatico della chiave primaria in un dl sqlite

Sintassi per creare il mio tavolo. Ho provato questo con/senza la AUTOINCREMENT

CREATE TABLE [TestTable] ([id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,[title] TEXT NULL) 

La mia classe TABELLA:

[Table(Name = "TestTable")] 
public class TestTable 
{ 
    [Column(IsPrimaryKey = true, IsDbGenerated =true)] 
    public int id { get; set; } 

    [Column] 
    public string title { get; set; } 
} 

Ecco come lo chiamo io. Quando si passa a submit ottengo un errore, incollo l'errore sotto questo esempio. Una cosa da notare è che se tolgo lo IsDbGenerated =true sopra e inserisco manualmente lo id inserisco bene, ma mi piacerebbe farlo a AUTOINCREMENT e per qualche motivo lo IsDbGenerated=true sta uccidendo l'inserto. Alla ricerca di una guida.

static void Main(string[] args) 
{ 
    string connectionString = @"DbLinqProvider=Sqlite;Data Source = c:\pathToDB\test.s3db"; 
    SQLiteConnection connection = new SQLiteConnection(connectionString); 
    DataContext db = new DataContext(connection); 
    db.Log = new System.IO.StreamWriter(@"c:\pathToDB\mylog.log") { AutoFlush = true }; 

    var com = db.GetTable<TestTable>(); 
    com.InsertOnSubmit(new TestTable {title = "asdf2" }); 
    try { 
     db.SubmitChanges(); 
    } 
    catch(SQLiteException e) 
    { 
     Console.WriteLine(e.Data.ToString()); 
     Console.WriteLine(e.ErrorCode); 
     Console.WriteLine(e.HelpLink); 
     Console.WriteLine(e.InnerException); 
     Console.WriteLine(e.Message); 
     Console.WriteLine(e.StackTrace); 
     Console.WriteLine(e.TargetSite); 
     Console.WriteLine(e.ToString()); 
    } 
    foreach (var TestTable in com) 
    { 
     Console.WriteLine("TestTable: {0} {1}", TestTable.id, TestTable.title); 
    } 
    Console.ReadKey(); 
} 

Messaggio di errore:

errore logico SQL o mancante del database \ r \ nnear \ "SELEZIONE \": errore di sintassi

traccia stack:

a System.Data.SQLite.SQLite3.Prepare (SQLiteConnection cnn, String strSql, SQLiteStatement precedente, Timeout UInt32 MS, String & strRemain) \ r \ n al System.Data.SQLite.SQLiteCommand.BuildNextCommand() \ r \ n al System.Data.SQLite.SQLiteCommand.GetStatement (indice Int32) \ r \ n al sistema .Data.SQLite.SQLiteDataReader.NextResult() \ r \ n a System.Data.SQLite.SQLiteDataReader..ctor (SQLiteCommand cmd, CommandBehavior si comportano) \ r \ n a System.Data.SQLite.SQLiteCommand.ExecuteReader (CommandBehavior comportamento) \ r \ n al System.Data.SQLite.SQLiteCommand.ExecuteDbDataReader (CommandBehavior comportamento) \ r \ n al System.Data.Common.DbCommand.ExecuteReader() \ r \ n
a System.Data .Linq.SqlClient.SqlProvider.Execute (query di espressione, QueryInfo QueryInfo, IObjectReaderFactory fabbrica, oggetto [] parentArgs, Object [] userArgs, ICompiledSubQuery [] Subquery, Object LASTRESULT) \ r \ n al System.Data.Linq.SqlClient.SqlProvider.ExecuteAll (query Espressione, QueryInfo [] queryInfos, IObjectReaderFactory factory, Object [] userArguments, ICompiledSubQuery [] subQueries) \ r \ n a System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute (Expression query) \ r \ n al System.Data.Linq.ChangeDirector.StandardChangeDirector.DynamicInsert (TrackedObject articolo) \ r \ n al System.Data.Linq.ChangeDirector.StandardChangeDirector.Insert (TrackedObject ite m) \ r \ n al System.Data.Linq.ChangeProcessor.SubmitChanges (ConflictMode failureMode) \ r \ n al System.Data.Linq.DataContext.SubmitChanges (ConflictMode failureMode) \ r \ n al System.Data .Linq.DataContext.SubmitChanges() \ r \ n a SqlLinq.Program.Main (String [] args) nel programma.cs: linea 29"

Ecco quello che sto vedendo in uscita registro:

INSERT INTO [company]([title]) 
VALUES (@p0) 

SELECT CONVERT(Int,SCOPE_IDENTITY()) AS [value] 
-- @p0: Input String (Size = 4000; Prec = 0; Scale = 0) [asdf2] 
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.6.81.0 

SELECT [t0].[id], [t0].[title] 
FROM [company] AS [t0] 
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.6.81.0 

risposta

5

in base alla documentazione SQLite (A column declared INTEGER PRIMARY KEY will AUTOINCREMENT.) è sufficiente rimuovere AUTOINCREMENT nella creazione della tabella, scrivendo integer primary key è sufficiente.SQLite incrementerà automaticamente il vostro ids:

sqlite_cmd.CommandText = "CREATE TABLE [TestTable] ([id] INTEGER PRIMARY KEY NOT NULL , [title] TEXT)"; 

Inoltre non è necessario impostare IsDbGenerated = true nella classe TestTable e non si immette il id manualmente, lo fa inserire bene solo con l'inserimento di title:

com.InsertOnSubmit(new TestTable { title = "asdf2" });//will automatically increment id. 

Edit: tuo.210 dovrebbe assomigliare a questa società:

[Table(Name = "TestTable")] 
public class TestTable 
{ 
    [Column(IsPrimaryKey = true)] 
    public int? id { get; set; } 

    [Column] 
    public string title { get; set; } 
} 

Il risultato in SQLite Manager:

The result

+1

Ho provato in questo modo solo ora. Ho ricreato la tabella con il tuo esempio SQL e rimosso la proprietà IsDbGenerated.Esso entra nel primo record aggiungendo uno 0 per l'ID. Il secondo tentativo fallisce con lo stesso errore come la mia descrizione Questo è lo stesso comportamento che stavo vedendo prima. – Terco

+1

Cambia il tuo id in 'Nullable' in questo modo:' public int? id {get; set;} ' –

1

Come faccio a creare un campo AUTOINCREMENT

Risposta breve: Una colonna dichiarata INTEGER PRIMARY KEY esegue l'autoincremento

Risposta più lunga: Se dichiari che una colonna di una tabella è INTEGER PRIMARY KEY, ogni volta che inserisci un NULL in quella colonna della tabella, il NULL viene automaticamente convertito in un numero intero che è maggiore del valore più grande di quello colonna su tutte le altre righe della tabella o 1 se la tabella è vuota. Oppure, se è in uso la chiave intera esistente più grande 9223372036854775807, viene scelto in modo casuale un valore chiave non utilizzato. Ad esempio, si supponga di avere una tabella come questa:

CREATE TABLE t1(
    a INTEGER PRIMARY KEY, 
    b INTEGER 
); 

Con questa tabella, la dichiarazione

INSERT INTO t1 VALUES(NULL,123); 

è logicamente equivale a dire:

INSERT INTO t1 VALUES((SELECT max(a) FROM t1)+1,123); 

C'è una funzione denominata sqlite3_last_insert_rowid() che restituirà la chiave intera per l'operazione di inserimento più recente.

Si noti che il numero intero è uno maggiore della chiave più grande che era nella tabella appena prima dell'inserto. La nuova chiave sarà univoca su tutte le chiavi attualmente presenti nella tabella, ma potrebbe sovrapporsi alle chiavi che sono state precedentemente eliminate dalla tabella . Per creare chiavi che siano univoche per tutta la durata della tabella, aggiungere la AUTOINCREMENT parola chiave alla dichiarazione INTEGER PRIMARY KEY. Quindi la chiave scelta sarà una più grande della chiave più grande mai esistita in quella tabella. Se la chiave più grande possibile è già esistita in quella tabella, quindi il INSERT avrà esito negativo con un codice di errore SQLITE_FULL.

Riferimenti:

Autoincrement in SQLite

How to create Autoincrement Field ?

SO post dealing with Autoincrement in SQLite

+0

È facilmente possibile che mi manca sopra ma non vedo un riferimento a come farlo con linq. Sono in grado di gestire l'incremento automatico senza problemi quando si utilizza SQL diretto e non si usa linq. (System.Data.Linq.Mapping – Terco

0

SqlLite non funziona con Linq comandi per autoincrement valori Questo comando produce errore

SELECT CONVERT(Int,SCOPE_IDENTITY()) AS [value] 

Hai solo 2 vie:

  1. Non utilizzare Linq per SQLLite. Utilizzare alcune soluzioni di terze parti o i propri comandi .

  2. Utilizzare altri modi per inrement vostro ID, come è stato scritto da [utilità]

La prima meglio, perché ci sono altri esempi di istruzioni SQL vengono passati al SQLite attraverso Linq che aren' t valido.