首页 > 解决方案 > 使用 sqlbulktools 更新表时对列值求和

问题描述

我正在使用 SqlBulkTools nuget 包来更新数百行数据。我在网上找到的示例涉及指定复制到表中的特定值。

是否可以将值添加/求和到现有存储值?例如,假设“Count”列的值为 200。我想将其更新 128,是否可以使用 SqlBulkTools?

标签: c#sqldatatablesqlbulktools

解决方案


SqlBulkTools 的主要用例是将数据直接导入您的数据库,因此不会有任何功能或事件可以让您直接定义要在批量操作期间执行的操作。BuildPreparedDataTable()可能是您正在寻找的,但我以前从未使用过它,所以我不能自信地说。

相反,您最好的选择是在将数据与 SqlBulkTools 挂钩之前对其进行修改。有多种方法可以实现这一点。

  1. 放弃 SqlBulkTools,改用存储过程。
  2. 使用 LINQ 直接翻译。
  3. 设置 AutoMapper,然后创建自己的 IValueResolver。

选项 1:存储过程

虽然不使用 SqlBulkTools,但这可能是最简单和最有效的选项,因为您可以引用正在更新的表。

CREATE PROCEDURE dbo.Add128ToCount
    @StartDate DATETIME,
    @EndDate DATETIME
AS
BEGIN
    SET NOCOUNT ON;
    
    UPDATE st SET [Count] = st.[Count] + 128
    FROM dbo.SomeTable st
    WHERE st.LastModifiedDate BETWEEN @StartDate AND @EndDate;
END

对于那些需要在表之间而不是同一个表之间进行某种数据修改的人,创建一个与表结构匹配的用户定义表类型,然后使用该类型将表值参数添加到存储过程中。(更多信息

CREATE PROCEDURE dbo.Add128ToCount
    @TVP SomeOtherTableType READONLY
AS
BEGIN
    SET NOCOUNT ON;
    
    INSERT INTO dbo.SomeTable
    (
        Name,
        [Count]
    )
    SELECT Name,
        [Count] + 128 AS [Count]
    FROM @TVP;
END

选项 2:LINQ

如果您必须使用 SqlBulkTools(例如,如果您没有数据库访问权限),您可以使用 LINQ 完成与选项 1 相同的事情。(更多信息

List<DestType> dest = (from s in source
                       select new DestType
                       {
                           Id = s.Id,
                           Name = s.Name,
                           Count = s.Count + 128
                       }).ToList();

选项 3:AutoMapper IValueResolver

如果您只需要执行一次这样的操作,则此选项将是多余的,因为涉及很多设置,包括配置 AutoMapper 和定义配置文件。但是,在您使用多个表甚至多个数据库的情况下,这是一个很好的长期解决方案。对于此处的特定用例,您的个人资料将如下所示:

class SomeTableProfile : Profile
{
    public SomeTableProfile()
    {
        SourceMemberNamingConvention = new PascalCaseNamingConvention();
        DestinationMemberNamingConvention = new PascalCaseNamingConvention();
        CreateMap<SourceType, DestType>()
            .ForMember(dest => dest.Count, opt => opt.MapFrom<Add128ToCountResolver>());
    }
}

然后,您将制作一个自定义 IValueResolver,如下所示:

class Add128ToCountResolver : IValueResolver<SourceType, DestType, int>
{
    public int Resolve(SourceType source, DestType destination, int destCount, ResolutionContext context)
    {
        return source.Count + 128;
    }
}

(更多关于 AutoMapper ) (更多关于值解析器)


推荐阅读