具有用户定义表类型的 SQL Server 存储过程
Posted
技术标签:
【中文标题】具有用户定义表类型的 SQL Server 存储过程【英文标题】:SQL Server stored procedure with user-defined table type 【发布时间】:2021-11-04 08:35:32 【问题描述】:我在 SQL Server 中有一个带有参数 @Files
的存储过程,它是用户定义的表类型。从 C# 代码执行时出现错误:
System.Data.SqlClient.SqlException: '传入的表格数据流 (TDS) 远程过程调用 (RPC) 协议流不正确。表值参数 3 ("@Files"),第 0 行,第 0 列:数据类型 0xF3(用户定义的表类型)具有指定的非零长度数据库名称。数据库名称不允许与表值参数一起使用,只有模式名称和类型名称有效。'
这是我的 C# 代码:
DataTable dt = new DataTable();
dt.Columns.Add("ComputerId", typeof(int));
dt.Columns.Add("FolderId", typeof(int));
dt.Columns.Add("FilePath", typeof(string));
dt.Columns.Add("FileName", typeof(string));
dt.Columns.Add("Size", typeof(long));
dt.Columns.Add("LastWriteTimeUtc", typeof(DateTime));
dt.Columns.Add("ReadOnly", typeof(bool));
foreach (var item in listFileInformation)
dt.Rows.Add(1, 1, item.FilePath, item.FileName, item.Size, item.LastWriteUTC, item.ReaddOnly);
databaseHelper.AddParameter("@ComputerId", 1);
databaseHelper.AddParameter("@FolderId", 1);
SqlParameter tableTypeParam = new SqlParameter("@Files", SqlDbType.Structured)
TypeName = "Inbox.dbo.EngComputerFileTableType",
Value = dt
;
databaseHelper.AddParameter(tableTypeParam);
databaseHelper.ExecuteNonQuery("InsertEngComputerFiles", System.Data.CommandType.StoredProcedure, System.Data.ConnectionState.Open);
databaseHelper.connection.Close();
这是存储过程:
CREATE PROCEDURE [dbo].[InsertEngComputerFiles]
@ComputerId BIGINT,
@FolderId BIGINT,
@Files [dbo].[EngComputerFileTableType] READONLY
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO
[Inbox].[dbo].[EngComputerFile] (
[ComputerId], [FolderId], [FilePath], [FileName],
[Size], [LastWriteTimeUtc], [ReadOnly])
SELECT
@ComputerId, @FolderId, [FilePath], [FileName],
[Size], [LastWriteTimeUtc], [ReadOnly]
FROM
@Files;
UPDATE [Inbox].[dbo].[EngComputer]
SET [LastScanTimeStampUtc] = SYSUTCDATETIME()
WHERE [ComputerId] = @ComputerId;
END
【问题讨论】:
你为什么说TypeName = "Inbox.dbo.EngComputerFileTableType"
而不是TypeName = "dbo.EngComputerFileTableType"
?该类型必须与您调用的存储过程在同一个数据库中才能正常工作,因此数据库前缀是不必要的(错误消息告诉您它不仅不必要而且无效)。
@AaronBertrand 感谢您的回复!但是我已经尝试过 dbo.EngComputerFileTableType 但它也给出了错误'Invalid object name 'Inbox.dbo.EngComputerFile'。'
dbo.EngComputerFile
dbo.EngComputerFileTableType
@MiralShah .
@Larnu 是真的!!!
不要在没有很好理由的情况下使用三部分名称。您的连接应确定数据库上下文。随着数据库在环境之间迁移,这些数据库的名称经常发生变化。使用 3 部分名称只会创建更多工作来支持这种非常常见的做法。
【参考方案1】:
消息说明一切 你需要改变这一行
SqlParameter tableTypeParam = new SqlParameter("@Files", SqlDbType.Structured)
//TypeName = "Inbox.dbo.EngComputerFileTableType",
TypeName = "dbo.EngComputerFileTableType",
Value = dt
;
【讨论】:
以上是关于具有用户定义表类型的 SQL Server 存储过程的主要内容,如果未能解决你的问题,请参考以下文章
使用 JDBC 将用户定义的表类型传递给 SQL Server 存储过程