使用 SqlBulkCopy 连接到 SQLite 数据库
Connecting to a SQLLite db with SqlBulkCopy
我正在用 c# 为负责使用 System.Data.SqlClient.SqlBulkCopy 将 DataTable 复制到数据库服务器的函数编写单元测试。
我使用 SQLLite 进行单元测试,并希望使用 SqlBulkCopy 连接到内存数据库中的 SQLLite,然后将该测试数据批量复制到 SQLLite 数据库中。
但是,我似乎无法获得正确的连接字符串。
我最初尝试过
var bcp = new SqlBulkCopy("FullUri=file::memory:?cache=shared")
然后
var bcp = new SqlBulkCopy("Data Source=:memory:;Cache=Shared")
哪个没认出来Cache
然后我尝试了
var bcp = new SqlBulkCopy("Data Source=:memory:")
出于绝望,尝试连接数据库时超时。
我在这里尝试实现的目标可行吗?如果是,有人可以帮我连接字符串吗?
您不能对 SQLite 使用 SqlBulkCopy
。 SqlBulkCopy
已为 SQL 服务器完成。
通常显着提高 SQLite 性能的技巧是确保使用事务。
免责声明:我是.NET Bulk Operations
的所有者
这个库不是免费的,但允许您轻松执行和自定义所有批量操作:
- 批量插入
- 批量删除
- 批量更新
- 批量合并
例子
// Easy to use
var bulk = new BulkOperation(connection);
bulk.BulkInsert(dt);
bulk.BulkUpdate(dt);
bulk.BulkDelete(dt);
bulk.BulkMerge(dt);
// Easy to customize
var bulk = new BulkOperation<Customer>(connection);
bulk.BatchSize = 1000;
bulk.ColumnInputExpression = c => new { c.Name, c.FirstName };
bulk.ColumnOutputExpression = c => c.CustomerID;
bulk.ColumnPrimaryKeyExpression = c => c.Code;
bulk.BulkMerge(customers);
编辑: 回复评论
I want to load a data table from SQLite then "bulk copy" it in other databases
这种情况是可能的,但需要2个连接
DbConnection sourceConnection = // connection from the source
DbConnection destinationConnection = // connection from the destination
// Fill the DataTable using the sourceConnection
dt = ...;
// BulkInsert using the destinationConnection
var bulk = new BulkOperation(destinationConnection);
bulk.BulkInsert(dt);
答案是您无法将 SqlBulkCopy 连接到 SQLite 实例。
我为解决问题(对使用 SqlBulkCopy 的代码的一部分进行单元测试)所做的工作是围绕 SqlBulkCopy 创建一个包装器,该包装器使用 SqlBulkCopy 实现生产代码,并在测试代码中使用模拟批量复制。有效解耦对SqlBulkCopy自身的依赖。
具体来说,我创建了
public interface IBulkCopy : IDisposable {
string DestinationTableName { get; set; }
void CreateColumnMapping(string from, string to);
Task WriteToServerAsync(DataTable dt);
}
然后,我将其实现为
public class SQLBulkCopy : IBulkCopy {
private SqlBulkCopy _sbc;
public string DestinationTableName {
get { return _sbc.DestinationTableName; }
set { _sbc.DestinationTableName = value; }
}
public SQLBulkCopy(IDBContext ctx) {
_sbc = new SqlBulkCopy((SqlConnection)ctx.GetConnection());
}
public void CreateColumnMapping(string from, string to) {
_sbc.ColumnMappings.Add(new SqlBulkCopyColumnMapping(from, to));
}
public Task WriteToServerAsync(DataTable dt) {
return _sbc.WriteToServerAsync(dt);
}
}
在我的测试实用程序中,我模拟了 "bulk copy",只插入了:
class MockBulkCopy : IBulkCopy {
private IDBContext _context;
public MockBulkCopyHelper(IDBContext context) {
_context = context;
}
public string DestinationTableName { get; set; }
public void CreateColumnMapping(string fromName, string toName) {
//We don't need a column mapping for raw SQL Insert statements.
return;
}
public virtual Task WriteToServerAsync(DataTable dt) {
return Task.Run(() => {
using (var cn = _context.GetConnection()) {
using (var cmd = cn.CreateCommand()) {
cmd.CommandText = $"INSERT INTO {DestinationTableName}({GetCsvColumnList(dt)}) VALUES {GetCsvValueList(dt)}";
cmd.ExecuteNonQuery();
}
}
});
}
其中 GetCsvColumnList
和 GetCsvValueList
我实现为辅助函数。
我正在用 c# 为负责使用 System.Data.SqlClient.SqlBulkCopy 将 DataTable 复制到数据库服务器的函数编写单元测试。
我使用 SQLLite 进行单元测试,并希望使用 SqlBulkCopy 连接到内存数据库中的 SQLLite,然后将该测试数据批量复制到 SQLLite 数据库中。
但是,我似乎无法获得正确的连接字符串。
我最初尝试过
var bcp = new SqlBulkCopy("FullUri=file::memory:?cache=shared")
然后
var bcp = new SqlBulkCopy("Data Source=:memory:;Cache=Shared")
哪个没认出来Cache
然后我尝试了
var bcp = new SqlBulkCopy("Data Source=:memory:")
出于绝望,尝试连接数据库时超时。
我在这里尝试实现的目标可行吗?如果是,有人可以帮我连接字符串吗?
您不能对 SQLite 使用 SqlBulkCopy
。 SqlBulkCopy
已为 SQL 服务器完成。
通常显着提高 SQLite 性能的技巧是确保使用事务。
免责声明:我是.NET Bulk Operations
的所有者这个库不是免费的,但允许您轻松执行和自定义所有批量操作:
- 批量插入
- 批量删除
- 批量更新
- 批量合并
例子
// Easy to use
var bulk = new BulkOperation(connection);
bulk.BulkInsert(dt);
bulk.BulkUpdate(dt);
bulk.BulkDelete(dt);
bulk.BulkMerge(dt);
// Easy to customize
var bulk = new BulkOperation<Customer>(connection);
bulk.BatchSize = 1000;
bulk.ColumnInputExpression = c => new { c.Name, c.FirstName };
bulk.ColumnOutputExpression = c => c.CustomerID;
bulk.ColumnPrimaryKeyExpression = c => c.Code;
bulk.BulkMerge(customers);
编辑: 回复评论
I want to load a data table from SQLite then "bulk copy" it in other databases
这种情况是可能的,但需要2个连接
DbConnection sourceConnection = // connection from the source
DbConnection destinationConnection = // connection from the destination
// Fill the DataTable using the sourceConnection
dt = ...;
// BulkInsert using the destinationConnection
var bulk = new BulkOperation(destinationConnection);
bulk.BulkInsert(dt);
答案是您无法将 SqlBulkCopy 连接到 SQLite 实例。
我为解决问题(对使用 SqlBulkCopy 的代码的一部分进行单元测试)所做的工作是围绕 SqlBulkCopy 创建一个包装器,该包装器使用 SqlBulkCopy 实现生产代码,并在测试代码中使用模拟批量复制。有效解耦对SqlBulkCopy自身的依赖。
具体来说,我创建了
public interface IBulkCopy : IDisposable {
string DestinationTableName { get; set; }
void CreateColumnMapping(string from, string to);
Task WriteToServerAsync(DataTable dt);
}
然后,我将其实现为
public class SQLBulkCopy : IBulkCopy {
private SqlBulkCopy _sbc;
public string DestinationTableName {
get { return _sbc.DestinationTableName; }
set { _sbc.DestinationTableName = value; }
}
public SQLBulkCopy(IDBContext ctx) {
_sbc = new SqlBulkCopy((SqlConnection)ctx.GetConnection());
}
public void CreateColumnMapping(string from, string to) {
_sbc.ColumnMappings.Add(new SqlBulkCopyColumnMapping(from, to));
}
public Task WriteToServerAsync(DataTable dt) {
return _sbc.WriteToServerAsync(dt);
}
}
在我的测试实用程序中,我模拟了 "bulk copy",只插入了:
class MockBulkCopy : IBulkCopy {
private IDBContext _context;
public MockBulkCopyHelper(IDBContext context) {
_context = context;
}
public string DestinationTableName { get; set; }
public void CreateColumnMapping(string fromName, string toName) {
//We don't need a column mapping for raw SQL Insert statements.
return;
}
public virtual Task WriteToServerAsync(DataTable dt) {
return Task.Run(() => {
using (var cn = _context.GetConnection()) {
using (var cmd = cn.CreateCommand()) {
cmd.CommandText = $"INSERT INTO {DestinationTableName}({GetCsvColumnList(dt)}) VALUES {GetCsvValueList(dt)}";
cmd.ExecuteNonQuery();
}
}
});
}
其中 GetCsvColumnList
和 GetCsvValueList
我实现为辅助函数。