且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

通过实体框架将表值类型传递给 SQL Server 存储过程

更新时间:2022-02-13 08:37:50

假设您想发送一个包含单列 GUID 的表格.

Lets say you want to send a table with a single column of GUIDs.

首先我们需要使用 SqlMetaData 表示表(列)的模式.

First we need to create a structure using SqlMetaData which represents the schema of the table (columns).

下面的代码演示了一个名为Id"的列GUID的就是SQL存储过程参数表类型

The below code demonstrates one column named "Id" of the GUID is the SQL stored procedure parameter table type

var tableSchema = new List<SqlMetaData>(1)
{
  new SqlMetaData("Id", SqlDbType.UniqueIdentifier)
}.ToArray();

接下来,您使用 SqlDataRecord.

下面的代码演示了如何使用上面创建的架构在列表中添加项目.为列表中的每个项目创建一个新的 SqlDataRecord.将 SetGuid 替换为相应的类型,并将 Guid.NewGuid() 替换为相应的值.对每个项目重复新的 SqlDataRecord 并将它们添加到 List

The below code demonstrates how to add the items inside a list using the above created schema. Create a new SqlDataRecord for each of the items in the list. Replace SetGuid with the corresponding type and Replace Guid.NewGuid() as the corresponding value. Repeat new SqlDataRecord for each item and add them to a List

var tableRow = new SqlDataRecord(tableSchema);
tableRow.SetGuid(0, Guid.NewGuid());
var table = new List<SqlDataRecord>(1)
{
  tableRow
};

然后创建SqlParameter:

var parameter = new SqlParameter();
parameter.SqlDbType = SqlDbType.Structured;
parameter.ParameterName = "@UserIds"; //@UserIds is the stored procedure parameter name
parameter.TypeName = "{Your stored procedure type name}"
parameter.Value = table;

var parameters = new SqlParameter[1]
{
  parameter
};

然后只需使用 Database.SqlQuery.

IEnumerable<ReturnType> result;
using (var myContext = new DbContext())
{
  result = myContext.Database.SqlQuery<User>("GetUsers @UserIds", parameters)
    .ToList();         // calls the stored procedure
    // ToListAsync();  // Async
{

在 SQL Server 中,创建您的用户定义表类型(我将它们后缀为 TTV,表类型值):

In SQL Server, create your User-Defined Table Type (I suffix them with TTV, Table Typed Value):

CREATE TYPE [dbo].[UniqueidentifiersTTV] AS TABLE(
  [Id] [uniqueidentifier] NOT NULL
)
GO

然后将类型指定为参数(不要忘记,表类型值必须是只读的!):

Then specify the type as a parameter (don't forget, Table Type Values have to be readonly!):

CREATE PROCEDURE [dbo].[GetUsers] (
  @UserIds [UniqueidentifiersTTV] READONLY
) AS
BEGIN
  SET NOCOUNT ON

  SELECT u.* -- Just an example :P
  FROM [dbo].[Users] u
  INNER JOIN @UserIds ids On u.Id = ids.Id
END