使用SqlBulkCopy连接到SQLLite数据库

时间:2017-11-08 21:42:58

标签: c# sqlite unit-testing sqlbulkcopy

我正在c#中编写一个单元测试,负责使用System.Data.SqlClient.SqlBulkCopy将DataTable复制到数据库服务器。

我使用SQLLite进行单元测试,并希望使用SqlBulkCopy连接到内存数据库中的SQLLite,然后将该测试数据批量复制到SQLLite数据库中。

但是,我似乎无法正确获取连接字符串。

我最初尝试过

var bcp = new SqlBulkCopy("Data Source=:memory:;Cache=Shared")

然后

Cache

哪些人无法识别var bcp = new SqlBulkCopy("Data Source=:memory:") 所以我试过

val iMax = graph.map{ g => g.i }.max
val jMax = graph.map{ g => g.j }.max

val theMax = math.max(iMax,jMax)

出于绝望,在尝试连接数据库时只是超时。

我在这里想要完成的是什么?如果是,有人可以帮我解决连接字符串吗?

2 个答案:

答案 0 :(得分:1)

您不能将SqlBulkCopy用于SQLite。已为SQL Server完成SqlBulkCopy

通常,显着提高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);

编辑:回答评论

  

我想从SQLite加载数据表,然后在其他数据库中“批量复制”它

这种情况是可能的,但需要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);

答案 1 :(得分:1)

此问题的答案是您无法将SqlBulkCopy连接到SQLite实例。

我解决问题的方法(对使用SqlBulkCopy的部分代码进行单元测试)是围绕SqlBulkCopy创建一个包装,该包装使用SqlBulkCopy进行生产代码实现,并在测试代码中使用模拟批量复制。有效地解耦对SqlBulkCopy本身的依赖关系。

具体地说,我创建了

public interface IBulkCopy : IDisposable {
    public string DestinationTableName {get;set;}
    public void CreateColumnMapping(string from, string to);
    public 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);
    }

}

在我的测试实用程序中,我只用插入内容就模拟了“批量复制”:

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处实现了辅助功能。

相关问题