使用 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 使用 SqlBulkCopySqlBulkCopy 已为 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();
                }
            }
        });
    }

其中 GetCsvColumnListGetCsvValueList 我实现为辅助函数。