我正在尝试打开一个Sqlite文件,并在Mono的表中插入一行。我引用了Mono.Data.Sqlite
,System.Data
和System.Data.Linq
程序集。 Sqlite文件和表都存在。 Status
类具有Table
和Column
属性。当我单独使用Mono的Sqlite库时,我可以成功插入。
Status data = GetStatusFoo();
using (SqliteConnection con = new SqliteConnection("Data Source=" + Config.SQLITE_DB_FILE + ";Version=3;"))
{
con.Open();
using (SqliteCommand cmd = new SqliteCommand("INSERT INTO " + _table + _insert + " VALUES " + _values, con))
{
cmd.Parameters.Add(new SqliteParameter("@Timestamp", data.Timestamp));
// ...
cmd.ExecuteNonQuery();
}
con.Close()
}
但是,我不想输出1000个SqliteParameters,所以我正在尝试使用Linq-to-SQL。以下代码在DataContext
构造函数中抛出TargetInvocationException。
Status data = GetStatusFoo();
using (DataContext db = new DataContext("Data Source=" + Config.SQLITE_DB_FILE + ";Version=3;"))
{
Table<Status> statuses = db.GetTable<Status>();
statuses.InsertOnSubmit(data);
db.SubmitChanges();
}
它抱怨Version
不是有效的关键字,所以当我删除它时,只留下
Status data = GetStatusFoo();
using (DataContext db = new DataContext("Data Source=" + Config.SQLITE_DB_FILE + ";")
{
Table<Status> statuses = db.GetTable<Status>();
statuses.InsertOnSubmit(data);
db.SubmitChanges();
}
它在db.SubmitChanges()
抛出一个System.Data.SqlClient.SqlException,表示“服务器不存在或连接被拒绝”。
但是,当我使用SqliteConnection进行DataContext的IDbConnection时,这会发生变化,即
Status data = GetStatusFoo();
using (SqliteConnection con = new SqliteConnection("Data Source=" + Config.SQLITE_DB_FILE + ";"))
using (DataContext db = new DataContext(con))
{
Table<Status> statuses = db.GetTable<Status>();
statuses.InsertOnSubmit(data);
db.SubmitChanges();
}
这会在SQLite error unrecognized token: "@"
处抛出Mono.Data.Sqlite.SqliteException:db.SubmitChanges();
。
添加Version=3;
没有帮助,尝试Version=2
会抛出System.NotSupportedException。 Console和DataContext.Log给出如下内容:
INSERT INTO [Status] ([Timestamp], ...) VALUES (@Timestamp, ...)
-- @Timestamp: Input Int64 (Size = 0; Prec = 0; Scale = 0) [1397710927]
-- ...
-- Context: SqlServer Model: AttributedMetaModel Build: 4.0.0.0
SELECT @@IDENTITY
-- @Timestamp: Input Int64 (Size = 0; Prec = 0; Scale = 0) [1397710927]
-- Context: SqlServer Model: AttributedMetaModel Build: 4.0.0.0
Unhandled Exception:
Mono.Data.Sqlite.SqliteException: SQLite error
unrecognized token: "@"
是什么给出的?为什么它不喜欢“@”符号?是否未能进行参数替换?或者最后是@@IDENTITY
来电?
编辑:其他信息
在堆栈跟踪之后,在Mono.Data.SqliteCommand.BuildNextCommand和this.CommandText
== "SELECT @@IDENTITY"
中发生SqliteException异常。显然,SQLite不支持此MS / Transact-SQL命令。据我所知,在DbLinq.Data.Linq.Sugar.Implementation.QueryRunner.Upsert (target={Status}, insertQuery={DbLinq.Data.Linq.Sugar.UpsertQuery})
所以我正在改变我的问题包括:我如何告诉Linq避免仅使用SQL的命令?
答案 0 :(得分:1)
我对我的问题有部分答案。
将DbLinqProvider=sqlite;
添加到SqliteConnection查询字符串会告诉Linq-to-SQL使用SQLite命令,并修复"SELECT @@IDENTITY"
问题。此代码有效:
Status data = GetStatusFoo();
using (SqliteConnection con = new SqliteConnection("Data Source=" + Config.SQLITE_DB_FILE + ";DbLinqProvider=sqlite;"))
using (DataContext db = new DataContext(con))
{
Table<Status> statuses = db.GetTable<Status>();
statuses.InsertOnSubmit(data);
db.SubmitChanges();
}
但是,我仍然需要使用SqliteConnection
对象,因为new DataContext("Data Source=" + Config.SQLITE_DB_FILE + ";DbLinqProvider=sqlite;")
仍然会抛出&#34;服务器不存在或连接被拒绝&#34;异常。
编辑:完整答案
事实证明,如果没有DbLinqConnectionType
参数,DataContext默认使用System.Data.SqlClient.SqlConnection
进行连接。连接类型必须是程序集完全限定名称,因此以下代码适用于我:
// in Config
public static string SQLITE_CONNECTION_CLASS_AQN = typeof(Mono.Data.Sqlite.SqliteConnection).AssemblyQualifiedName
// in database class
static string _connection_string = "Data Source=" + Config.SQLITE_DB_FILE + ";DbLinqProvider=sqlite;DbLinqConnectionType=" + Config.SQLITE_CONNECTION_CLASS_AQN + ";";
// in database method
Status data = GetStatusFoo();
using (DataContext db = new DataContext(_connection_string))
{
Table<Status> statuses = db.GetTable<Status>();
statuses.InsertOnSubmit(data);
db.SubmitChanges();
}
供参考,typeof(Mono.Data.Sqlite.SqliteConnection).AssemblyQualifiedName
评估为"Mono.Data.Sqlite.SqliteConnection, Mono.Data.Sqlite, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"
。