使用 System.Data.Linq.Mapping 并自动递增 sqlite 数据库中的主键时出错
Error using System.Data.Linq.Mapping and auto incrementing the primary key in a sqlite db
我正在使用 SQLite
和 System.Data.Linq.Mapping
。使用 linq 映射属性 IsDbGenerated = true
.
时,id
AUTOINCREMENT
字段出现问题
创建我的 table 的语法。我试过这个 with/without AUTOINCREMENT
CREATE TABLE [TestTable] ([id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,[title] TEXT NULL)
我的TABLEclass:
[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<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();
}
错误信息:
SQL logic error or missing database\r\nnear \"SELECT\": syntax error
堆栈跟踪:
at System.Data.SQLite.SQLite3.Prepare(SQLiteConnection cnn, String
strSql, SQLiteStatement previous, UInt32 timeoutMS, String&
strRemain)\r\n at
System.Data.SQLite.SQLiteCommand.BuildNextCommand()\r\n at
System.Data.SQLite.SQLiteCommand.GetStatement(Int32 index)\r\n at
System.Data.SQLite.SQLiteDataReader.NextResult()\r\n at
System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd,
CommandBehavior behave)\r\n at
System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior
behavior)\r\n at
System.Data.SQLite.SQLiteCommand.ExecuteDbDataReader(CommandBehavior
behavior)\r\n at System.Data.Common.DbCommand.ExecuteReader()\r\n
at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query,
QueryInfo queryInfo, IObjectReaderFactory factory, Object[]
parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object
lastResult)\r\n at
System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query,
QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[]
userArguments, ICompiledSubQuery[] subQueries)\r\n at
System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression
query)\r\n at
System.Data.Linq.ChangeDirector.StandardChangeDirector.DynamicInsert(TrackedObject
item)\r\n at
System.Data.Linq.ChangeDirector.StandardChangeDirector.Insert(TrackedObject
item)\r\n at
System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode
failureMode)\r\n at
System.Data.Linq.DataContext.SubmitChanges(ConflictMode
failureMode)\r\n at System.Data.Linq.DataContext.SubmitChanges()\r\n
at SqlLinq.Program.Main(String[] args) in Program.cs:line 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
How do I create an AUTOINCREMENT field
简答:声明为 INTEGER PRIMARY KEY 的列将自动递增。
更长的答案: 如果您将 table 的列声明为 INTEGER PRIMARY KEY,那么每当您将 NULL 插入 [=51] 的该列时=],NULL 会自动转换为整数,该整数比 table 中该列的最大值大 1,如果 table 为空,则为 1。或者,如果最大的现有整数键 9223372036854775807 正在使用中,则随机选择一个未使用的键值。例如,假设您有一个像这样的 table:
CREATE TABLE t1(
a INTEGER PRIMARY KEY,
b INTEGER
);
有了这个table,声明
INSERT INTO t1 VALUES(NULL,123);
在逻辑上等同于说:
INSERT INTO t1 VALUES((SELECT max(a) FROM t1)+1,123);
有一个名为 sqlite3_last_insert_rowid()
的函数,它将 return 最近插入操作的整数键。
Note that the integer key is one greater than the largest key that was
in the table just prior to the insert. The new key will be unique over
all keys currently in the table, but it might overlap with keys that
have been previously deleted from the table. To create keys that are
unique over the lifetime of the table, add the AUTOINCREMENT
keyword
to the INTEGER PRIMARY KEY
declaration. Then the key chosen will be
one more than the largest key that has ever existed in that table. If
the largest possible key has previously existed in that table, then
the INSERT
will fail with an SQLITE_FULL error code.
参考资料:
How to create Autoincrement Field ?
SO post dealing with Autoincrement in SQLite
根据 SQLite 文档 (A column declared INTEGER PRIMARY KEY will AUTOINCREMENT.),只需删除 Table 创建中的 AUTOINCREMENT
,写 integer primary key
就足够了。 SQLite 会自动增加你的 ids
:
sqlite_cmd.CommandText = "CREATE TABLE [TestTable] ([id] INTEGER PRIMARY KEY NOT NULL , [title] TEXT)";
此外,您不需要在 TestTable
class 中设置 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 Manager 中的结果:
SQLLite 不适用于自动增量值的 Linq 命令
此命令产生错误
SELECT CONVERT(Int,SCOPE_IDENTITY()) AS [value]
你只有两种方式:
不要将 Linq 用于 SQLLite。使用一些第三方解决方案,或者您的
自己的命令。
使用其他方法来增加您的 ID,因为它是由 [utility]
编写的
第一个更好,因为还有其他 SQL 语句通过 Linq 传递给 sqlite 的例子是无效的。
我正在使用 SQLite
和 System.Data.Linq.Mapping
。使用 linq 映射属性 IsDbGenerated = true
.
id
AUTOINCREMENT
字段出现问题
创建我的 table 的语法。我试过这个 with/without AUTOINCREMENT
CREATE TABLE [TestTable] ([id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,[title] TEXT NULL)
我的TABLEclass:
[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<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();
}
错误信息:
SQL logic error or missing database\r\nnear \"SELECT\": syntax error
堆栈跟踪:
at System.Data.SQLite.SQLite3.Prepare(SQLiteConnection cnn, String strSql, SQLiteStatement previous, UInt32 timeoutMS, String& strRemain)\r\n at System.Data.SQLite.SQLiteCommand.BuildNextCommand()\r\n at System.Data.SQLite.SQLiteCommand.GetStatement(Int32 index)\r\n at System.Data.SQLite.SQLiteDataReader.NextResult()\r\n at System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)\r\n at System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)\r\n at System.Data.SQLite.SQLiteCommand.ExecuteDbDataReader(CommandBehavior behavior)\r\n at System.Data.Common.DbCommand.ExecuteReader()\r\n
at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult)\r\n at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries)\r\n at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)\r\n at System.Data.Linq.ChangeDirector.StandardChangeDirector.DynamicInsert(TrackedObject item)\r\n at System.Data.Linq.ChangeDirector.StandardChangeDirector.Insert(TrackedObject item)\r\n at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode)\r\n at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)\r\n at System.Data.Linq.DataContext.SubmitChanges()\r\n at SqlLinq.Program.Main(String[] args) in Program.cs:line 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
How do I create an AUTOINCREMENT field
简答:声明为 INTEGER PRIMARY KEY 的列将自动递增。
更长的答案: 如果您将 table 的列声明为 INTEGER PRIMARY KEY,那么每当您将 NULL 插入 [=51] 的该列时=],NULL 会自动转换为整数,该整数比 table 中该列的最大值大 1,如果 table 为空,则为 1。或者,如果最大的现有整数键 9223372036854775807 正在使用中,则随机选择一个未使用的键值。例如,假设您有一个像这样的 table:
CREATE TABLE t1(
a INTEGER PRIMARY KEY,
b INTEGER
);
有了这个table,声明
INSERT INTO t1 VALUES(NULL,123);
在逻辑上等同于说:
INSERT INTO t1 VALUES((SELECT max(a) FROM t1)+1,123);
有一个名为 sqlite3_last_insert_rowid()
的函数,它将 return 最近插入操作的整数键。
Note that the integer key is one greater than the largest key that was in the table just prior to the insert. The new key will be unique over all keys currently in the table, but it might overlap with keys that have been previously deleted from the table. To create keys that are unique over the lifetime of the table, add the
AUTOINCREMENT
keyword to theINTEGER PRIMARY KEY
declaration. Then the key chosen will be one more than the largest key that has ever existed in that table. If the largest possible key has previously existed in that table, then theINSERT
will fail with an SQLITE_FULL error code.
参考资料:
How to create Autoincrement Field ?
SO post dealing with Autoincrement in SQLite
根据 SQLite 文档 (A column declared INTEGER PRIMARY KEY will AUTOINCREMENT.),只需删除 Table 创建中的 AUTOINCREMENT
,写 integer primary key
就足够了。 SQLite 会自动增加你的 ids
:
sqlite_cmd.CommandText = "CREATE TABLE [TestTable] ([id] INTEGER PRIMARY KEY NOT NULL , [title] TEXT)";
此外,您不需要在 TestTable
class 中设置 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 Manager 中的结果:
SQLLite 不适用于自动增量值的 Linq 命令 此命令产生错误
SELECT CONVERT(Int,SCOPE_IDENTITY()) AS [value]
你只有两种方式:
不要将 Linq 用于 SQLLite。使用一些第三方解决方案,或者您的 自己的命令。
使用其他方法来增加您的 ID,因为它是由 [utility]
编写的
第一个更好,因为还有其他 SQL 语句通过 Linq 传递给 sqlite 的例子是无效的。