在Dapper中使用TVP和未提供参数的exe sproc?

时间:2017-04-28 14:36:23

标签: c# asp.net-core .net-core dapper

我有一个sproc(我们称之为 usp_SaveQuestionAnswer ),它会在应用程序中插入/更新申请人对任何给定问题的答案,这是对他们的期望参数类似于以下内容:

@answeredQuestionGuid UNIQUEIDENTIFIER,
@questionGuid UNIQUEIDENTIFIER,
@applicationId INT,
@applicantID INT,
@answerData tvp_AnswerData READONLY

并且tvp_AnswerData定义为:

answerGuid UNIQUEIDENTIFIER,
answerTypeId INT,
answerValue VARCHAR(300),
answerBoolValue BIT

sproc接受参数,并以字符串的形式返回错误,数据无效(错误类型,null不应该等等),或者根本不返回任何内容

如何执行此操作的明显答案(根据this)将是DynamicParameters,因为.Net Core不支持DataTables - 为tvp_AnswerData构建DynamicParameters对象,然后是第二个DynamicParameters对象(称为 dynamicParamsObject ),用于整个参数列表,将tvp_AnswerData DynamicParameters对象传递给该对象,然后使用以下命令执行sproc:

var result = _db.Query
(
    "usp_SaveQuestionAnswer",
    dynamicParamsObject,
    commandType: CommandType.StoredProcedure
);

不幸的是,据我所知,DynamicParameters并不知道如何处理DynamicParameters类型的参数。

我这样做错了吗?有没有什么方法Dapper可以处理将TVP与其他参数一起传递给sproc,除了写出sql命令,或者是我的选择要么重写DB还是使用Dapper以外的东西(例如SqlCommand)?

1 个答案:

答案 0 :(得分:2)

它不漂亮,但它有可能。以下是我的随机摘录中的一个示例:

CREATE TYPE [dbo].[DeptType] AS TABLE(
    [DeptId] [int] NULL,
    [DeptName] [varchar](100) NULL
)
GO

CREATE PROCEDURE [dbo].[InsertDepartment]
@InsertDept_TVP DeptType READONLY
AS
INSERT INTO Department(DepartmentID,DepartmentName)
SELECT * FROM @InsertDept_TVP;
GO

[Test]
public void Test()
{
    var conn = new SqlConnection(@"Data Source=.\sqlexpress;Integrated Security=true; Initial Catalog=foo");
    conn.Open();

    var x = new DataTable();
    x.SetTypeName("DeptType");
    x.Columns.Add("DeptId", typeof(int));
    x.Columns.Add("DeptName", typeof(string));

    var row = x.NewRow();
    row["DeptId"] = 1;
    row["DeptName"] = "Foo";
    x.Rows.Add(row);

    var row2 = x.NewRow();
    row2["DeptId"] = 2;
    row2["DeptName"] = "Bar";
    x.Rows.Add(row2);

    conn.Execute("InsertDepartment", new { InsertDept_TVP = x.AsTableValuedParameter("DeptType") }, commandType: CommandType.StoredProcedure);
}