C# call store procedure with table input parameters
有时候我们调用SQL server的存储过程的时候,需要批量传入表数据(比如表字段包括[UserId],[CompanyId], [DealId], [RoleId]),而并不是简单的传入@Ids或者一些简单的参数(例如 @UserId int, @DealId int)。
此文章介绍利用SQL Server 的User Defined Type实现table作为存储过程的入参,然后如何用C#去调用存储过程的方法。
目录
1. 创建User Defined Type
2. 创建存储过程
3. C#代码调用
4. SQL Profile检测到的执行脚本
1. 创建User Defined Type
CREATE TYPE [dbo].[udTestDemo] AS TABLE
(UserId INT,CompanyId INT, DealId INT, RoleId INT, IsAdded bit
)GO
2. 创建存储过程
/*
Description: Test demo
2025-11-13 Evan Created Test Demo:declare @p1 [dbo].[udTestDemo]
insert into @p1 values(88934,48456,37961,25,1)
insert into @p1 values(194194,48456,37961,25,1)exec SP_TEST_USER_DEFINED_TYPE_AS_INPUT_PARAMETERS @AddOrRemovedItems=@p1,@ApproverUserId=174963*/
CREATE PROCEDURE [dbo].[SP_TEST_USER_DEFINED_TYPE_AS_INPUT_PARAMETERS]@AddOrRemovedItems [dbo].[udTestDemo] READONLY,@ApproverUserId int
AS
BEGIN-- Insert;WITH AddedItems as (select [UserId],[CompanyId], [DealId], [RoleId] from @AddOrRemovedItems where IsAdded = 1)select [UserId],[CompanyId], [DealId], [RoleId] from AddedItems--Delete;WITH RemovedItems as (select [UserId],[CompanyId], [DealId], [RoleId] from @AddOrRemovedItems where IsAdded = 0)select [UserId],[CompanyId], [DealId], [RoleId] from RemovedItems
END
3. C#代码调用
/// <summary>
/// RelationShip
/// </summary>
public class RelationShip
{/// <summary>/// UserId/// </summary>public int UserId { get; set; }/// <summary>/// DealId/// </summary>public int DealId { get; set; }/// <summary>/// CompanyId/// </summary>public int CompanyId { get; set; }
}
调用方法
private const int AGENCY_CLIENT_ROLE_ID = 25;/// <summary>
/// SaveRelationShips (Save Deal to Client).
/// Aka: Save Contact to one Deal
/// </summary>
/// <param name="approverUserId"></param>
/// <param name="addedRelations"></param>
/// <param name="removedRelations"></param>
/// <param name="roleId"></param>
/// <returns></returns>
private async Task<bool> SaveRelationShips(int approverUserId, List<RelationShip> addedRelations, List<RelationShip> removedRelations, int? roleId = 25)
{try{DataTable table = new();table.Columns.Add("UserId", typeof(int));table.Columns.Add("CompanyId", typeof(int));table.Columns.Add("DealId", typeof(int));table.Columns.Add("RoleId", typeof(int));table.Columns.Add("IsAdded", typeof(bool));if (addedRelations != null && addedRelations.Count > 0){foreach (RelationShip relationship in addedRelations){table.Rows.Add(relationship.UserId, relationship.CompanyId, relationship.DealId, roleId ?? AGENCY_CLIENT_ROLE_ID, true);}}if (removedRelations != null && removedRelations.Count > 0){foreach (RelationShip relationship in removedRelations){table.Rows.Add(relationship.UserId, relationship.CompanyId, relationship.DealId, roleId ?? AGENCY_CLIENT_ROLE_ID, false);}}using SqlConnection DbConnection = new SqlConnection(connectionString);DbConnection.Open();SqlCommand comm = new SqlCommand(CRM_GPRC_SP_SAVE_RELATIONSHIP_FOR_USER, DbConnection);comm.CommandType = CommandType.StoredProcedure;comm.CommandTimeout = 50;comm.Parameters.AddWithValue("@AddOrRemovedItems", table);comm.Parameters.AddWithValue("@ApproverUserId", approverUserId);var result = await comm.ExecuteNonQueryAsync();DbConnection.Close();return true;}catch (Exception ex){Log.Error(ex, $"SaveRelationShips failed. {ex.Message}");}return false;
}
4. SQL Profile检测到的执行脚本
declare @p1 [dbo].[udTestDemo]
insert into @p1 values(88934,48456,37961,25,1)
insert into @p1 values(194194,48456,37961,25,1)exec SP_TEST_USER_DEFINED_TYPE_AS_INPUT_PARAMETERS @AddOrRemovedItems=@p1,@ApproverUserId=174963
