SQLKata 插入不适用于 VARBINARY

问题描述 投票:0回答:1

我有这段代码,可以将数据插入到这样的表中:

public async Task<int> InsertRowAsync(InsertRowRequest request)
{
    using var conn = _dbConnectionContext.CreateConnection(request.DbAlias);
    using var db = new QueryFactory(conn, new SqlServerCompiler());

    var data = new List<KeyValuePair<string, object>>();
    for (int j = 0; j < request.ColumnNames.Length; j++)
    {
        data.Add(new KeyValuePair<string, object>(request.ColumnNames[j], request.RowItems[j].ToString()));
    }
    var id = await db.Query(request.TableName).InsertGetIdAsync<int>(data);
    return id;
}

这是请求 DTO:

public class InsertRowRequest
{
    public string DbAlias { get; set; }
    public string TableName { get; set; }
    public string[] ColumnNames { get; set; }
    public object[] RowItems { get; set; }
}

我现在面临的问题是,对于具有 varbinary 类型列的表,它会失败,我不知道是否有任何方法可以使其正常工作。

鉴于此设置(SQL Server):

create table SqlKataTable
(
    Id INT NOT NULL,
    Doc VARBINARY(MAX) NULL,
    DocType NVARCHAR(255) NULL
)

上述方法将生成一个用于插入的 SQL 脚本,如下所示:

exec sp_executesql N'INSERT INTO [SqlKataTable] ([Id], [Doc], [DocType]) VALUES (@p0, @p1, @p2);SELECT scope_identity() as Id'
,N'@p0 nvarchar(4000),@p1 nvarchar(max) ,@p2 nvarchar(4000)'
,@p0=N'19751',@p1=N'asdasdasd',@p2=N'pdf'

失败并显示此错误消息:

消息 257,第 16 级,状态 3,第 13 行 不允许从数据类型 nvarchar(max) 隐式转换为 varbinary(max)。使用 CONVERT 函数运行此查询。

问题在于,对于 varbinary 列,它会生成一个

@p1 nvarchar(max)
,这会使 SQL Server 失败。

关于如何使其与 varbinary 类型一起工作有什么想法吗?这基本上是用于 REST API 调用的控制器背后的方法 - 因此输入以 JSON 正文形式出现。

我意识到我有一个设计缺陷。

request.RowItems[j].ToString()
几乎适用于我测试过的所有情况,除了varbinary,我必须将从请求中获得的base64字符串编码为byte[],但它会弄乱添加的通用/动态该 API 的值。如果我将函数的主体更改为此(仅用于演示目的),它将起作用:

public async Task<int> InsertRowAsync(InsertRowRequest request)
    {
        using var conn = _dbConnectionContext.CreateConnection(request.DbAlias);
        using var db = new QueryFactory(conn, new SqlServerCompiler());

        var data = new List<KeyValuePair<string, object>>();
        for (int j = 0; j < request.ColumnNames.Length; j++)
        {
            if(request.RowItems[j].ToString().Length > 150)
                data.Add(new KeyValuePair<string, object>(request.ColumnNames[j], Encoding.UTF8.GetBytes(request.RowItems[j].ToString())));
            else
                data.Add(new KeyValuePair<string, object>(request.ColumnNames[j], request.RowItems[j].ToString()));
        }

        var id = await db.Query(request.TableName).InsertGetIdAsync<int>(data);
        return id;
    }
c# sql-server dapper sqlkata
1个回答
0
投票

我意识到我有一个设计缺陷。 request.RowItems[j].ToString()几乎适用于迄今为止我测试过的所有sql类型,除了varbinary,为此我必须将从请求中获得的base64字符串编码为byte[],但它会扰乱此 API 的通用/动态附加值。如果我将函数的主体更改为此(仅用于演示目的),它将起作用:

public async Task<int> InsertRowAsync(InsertRowRequest request)
    {
        using var conn = _dbConnectionContext.CreateConnection(request.DbAlias);
        using var db = new QueryFactory(conn, new SqlServerCompiler());

        var data = new List<KeyValuePair<string, object>>();
        for (int j = 0; j < request.ColumnNames.Length; j++)
        {
            if(request.RowItems[j].ToString().Length > 150)
                data.Add(new KeyValuePair<string, object>(request.ColumnNames[j], Encoding.UTF8.GetBytes(request.RowItems[j].ToString())));
            else
                data.Add(new KeyValuePair<string, object>(request.ColumnNames[j], request.RowItems[j].ToString()));
        }

        var id = await db.Query(request.TableName).InsertGetIdAsync<int>(data);
        return id;
    }

考虑到设计,我将实现一个缓存机制,我将缓存授权对象的元数据(因为我确实实现了一个授权文件,以限制和控制对数据库对象的访问),并基于该信息,我将实现此类列的编码。

© www.soinside.com 2019 - 2024. All rights reserved.