批量操作


1、Batch 方法

  Batch 方法可以将一个序列的实体一次性进行插入、更新或删除。在批量操作之前,先构造一个实体集。

[TestMethod]
public void TestBatchInsert()
{
    using (var db = new DbContext())
    {
        var list = new List<Products>();

        for (var i = 0; i < 10; i++)
        {
            var product = db.New<Products>();
            product.ProductName = "aa" + i;
            product.Discontinued = 0;
            list.Add(product);
        }

        db.Products.Batch(list, (u, s) => u.Insert(s));
    }
}

  Batch 方法的 lambda 表达式支持 Insert、Update 和 Delete 操作。使用 Update 或 Delete 时,应注意集合里的实体必须给定其主键值,否则将不能完成批量操作。

  使用批量操作时应注意,默认尾部下所生成的 SQL 语句是以第一个实体的属性状态做为参照的。如果集合中每个实体的属性可能不相同,则应指定 BatchCheckModifiedKinds.Everyone

[TestMethod]
public void TestBatchInsert()
{
    using (var db = new DbContext())
    {
        var list = new List<Products>();

        for (var i = 0; i < 10; i++)
        {
            var product = db.New<Products>();
            product.ProductName = "test" + i;
            product.Discontinued = 0;
            list.Add(product);
        }
        
        list[6].QuantityPerUnit = "kg"; //单独设置了某一个实体的某一个属性
        
        var options = new BatchOperateOptions(BatchCheckModifiedKinds.Everyone);

        db.Products.Batch(list, (u, s) => u.Insert(s), options);
    }
}

  你也可以使用 属性过滤 来设置需要插入或更新的属性。BatchOperateOptions 类有一个 PropertyFilter 属性,你可以添加要过滤的属性。如下所示:

[TestMethod]
public void TestBatchInsertWithPropertyFilter()
{
    using (var db = new DbContext())
    {
        var list = new List<Products>();

        for (var i = 0; i < 10; i++)
        {
            var product = db.New<Products>();
            product.ProductName = "test" + i;
            product.Discontinued = 0;
            list.Add(product);
        }
        
        list[6].QuantityPerUnit = "kg"; //单独设置了某一个实体的某一个属性
        
        var options = new BatchOperateOptions
        {
            PropertyFilter = PropertyFilter<Products>.Inclusive()
                .With(s => s.ProductName)
                .With(s => s.QuantityPerUnit)
        };

        db.Products.Batch(list, (u, s) => u.Insert(s), options);
    }
}

  使用批量操作插入的实体,你也可以获取到每一个实体的主键值。


2、UseBatch 扩展方法

  EntityContext 的扩展方法 UseBatch 将开启一个批执行范围,在此期间,所有的 Insert、Update 和 Delete 语句将合并为一条指令提交给数据库。这适用于不关注操作返回值但希望提高执行效率的情形下。如下所示:

[TestMethod]
public async Task TestUseBagch()
{
    using (var db = new DbContext())
    {
        await db.UseBatchAsync(async db =>
        {
            var order = await db.Orders.FirstOrDefaultAsync();
            await db.Orders.DeleteAsync(s => s.OrderDate == DateTime.Now && s.OrderID == order.OrderID);
            db.Customers.Delete(s => s.CustomerID == "test");
            db.Products.Delete(s => s.ProductName == "test");
        });
    }
}

💡 小提示

  UseBatch 方法范围内,Insert、Update 和 Delete 的同步/异步方法是同等的,不必刻意区分。即异步是由 UseBatchAsync 方法所决定的。