使用System.Data.Linq.Mapping并在sqlite数据库中自动递增主键时出错

我正在使用SQLiteSystem.Data.Linq.Mapping 。 当使用linq映射属性IsDbGenerated = true时,我遇到了id AUTOINCREMENT字段的问题。

创建表的语法。 我用/不用AUTOINCREMENT试过这个

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

我的TABLE类:

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

这是我如何称呼它。 提交时我收到错误,我会在此示例下面粘贴错误。 有一点需要注意的是,如果我取出上面的IsDbGenerated =true并手动输入id ,它确实插入正常,但是我想将它转换为AUTOINCREMENT并且出于某种原因IsDbGenerated=true正在杀死插入。 寻找一些指导。

 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(); 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(); } 

错误信息:

SQL逻辑错误或缺少数据库\ r \ nnene \“SELECT \”:语法错误

堆栈跟踪:

在System.Data.SQLite.SQLite3.Prepare(SQLiteConnection cnn,String strSql,SQLiteStatement previous,UInt32 timeoutMS,String&strRemain)\ r \ n在System.Data.SQLite.SQLiteCommand.BuildNextCommand()\ r \ n在System.Data在System.Data.SQLite.SQLiteDataReader..ctor的System.Data.SQLite.SQLiteDataReader.NextResult()\ r \ n中的.SQLite.SQLiteCommand.GetStatement(Int32 index)\ r \ n(SQLiteCommand cmd,CommandBehavior behave)\ r \ n \ n位于System.Data.Comite.DbCommand.ExecuteReader()的System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)\ r \ n,位于System.Data.SQLite.SQLiteCommand.ExecuteDbDataReader(CommandBehavior behavior)\ r \ n \ r \ n
在System.Data.Linq.SqlClient.SqlProvider.Execute(表达式查询,QueryInfo queryInfo,IObjectReaderFactory工厂,Object [] parentArgs,Object [] userArgs,ICompiledSubQuery [] subQueries,Object lastResult)\ r \ n在System.Data.Linq .SqlClient.SqlProvider.ExecuteAll(Expression query,QueryInfo [] queryInfos,IObjectReaderFactory factory,Object [] userArguments,ICompiledSubQuery [] subQueries)\ r \ n在System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider .IProvider.Execute(表达式查询)\ r \ n在System.Data.Linq.ChangeDirector.StandardChangeDirector.DynamicInsert(TrackedObject item)\ r \ n在System.Data.Linq.ChangeDirector.StandardChangeDirector.Insert(TrackedObject item)\ r \ n \ n at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode)\ r \ n at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)\ r \ n在System.Data.Linq.DataContext.SubmitChanges() \ r \ n在Program.cs中的SqlLinq.Program.Main(String [] args):第29行“

这是我在日志输出中看到的内容:

 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 

根据SQLite文档( 声明INTEGER PRIMARY KEY的列将AUTOINCREMENT。 )在表创建中删除AUTOINCREMENT ,写入integer primary key就足够了。 SQLite会自动增加你的ids

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

此外,您不需要在TestTable类中设置IsDbGenerated = true ,也不需要手动输入id ,只需插入title即可插入:

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

编辑:您的TestTable现在应该如下所示:

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

SQLite管理器中的结果:

结果

如何创建AUTOINCREMENT字段

简短回答 :声明为INTEGER PRIMARY KEY的列将自动递增。

更长的答案:如果您将表的一列声明为INTEGER PRIMARY KEY,那么无论何时向表的该列插入NULL,NULL都会自动转换为一个整数,该整数大于该列的最大值。表中的所有其他行,如果表为空,则为1。 或者,如果正在使用最大的现有整数密钥9223372036854775807,则随机选择未使用的密钥值。 例如,假设您有一个这样的表:

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

有了这个表,声明

 INSERT INTO t1 VALUES(NULL,123); 

在逻辑上等同于说:

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

有一个名为sqlite3_last_insert_rowid()的函数,它将返回最近插入操作的整数键。

请注意,整数键比插入前表中的最大键大1。 新密钥对于当前表中的所有密钥都是唯一的,但它可能与先前从表中删除的密钥重叠。 要创建在表的生命周期内唯一的键,请将AUTOINCREMENT关键字添加到INTEGER PRIMARY KEY声明中。 然后,所选择的密钥将比该表中存在的最大密钥多一个。 如果该表中先前存在最大可能键,则INSERT将失败并显示SQLITE_FULL错误代码。

参考文献:

SQLite中的自动增量

如何创建自动增量字段?

SO在SQLite中处理Autoincrement

SQLLite不能与Linq命令一起使用自动增量值此命令会产生错误

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

你只有两种方式:

  1. 不要将Linq用于SQLLite。 使用一些第三方解决方案或您自己的命令。

  2. 使用其他方式来修改您的ID,因为它是由[实用程序]编写的

第一个更好,因为有其他SQL语句的例子通过Linq传递给sqlite是无效的。