我有这个程序
CREATE PROCEDURE dbo.spProcedure1
@intArray as dbo.intArray READONLY
AS
BEGIN
-- ...
END
使用用户类型作为参数
CREATE TYPE dbo.IntArray AS TABLE (IntValue int NULL)
我正在调用C#ASP.NET MVC 4项目中的过程
// creating empty SQL @IntArray parameter
var emptyIntDataTable = new DataTable();
emptyIntDataTable.Columns.Add("IntValue");
// calling stored procedure
return Database.SqlQuery<int>(
@"spProcedure1 @p1",
new SqlParameter("p1", (object)Utils.ToDataTable(m.IntArray) ?? emptyIntDataTable)
).ToList();
// ToDataTable method which is returning null
public static DataTable ToDataTable<T>(this IList<T> data)
{
if (data == null)
return null;
... // code omitted because it is not working yet
}
调用存储过程时抛出的错误是
表类型参数“p1”必须具有有效的类型名称。
如何传递空表值?
传递列表而不是数据表抛出跟随错误
var emptyIntDataTable = new List<int>;
对象类型System.Collections.Generic.List`1 [[System.Int32,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]]不存在到已知托管提供程序本机类型的映射。
答案 0 :(得分:0)
在您的代码中:
它说:
return Database.SqlQuery<int>(
@"spProcedure1 @p1", new SqlParameter("p1",
(object)Utils.ToDataTable(m.IntArray) ?? emptyIntDataTable)
).ToList();
将其更改为:
return m.IntArray.Length > 0?
Database.SqlQuery<int>(@"spProcedure1 @p1",
new SqlParameter("p1",
(object)Utils.ToDataTable(m.IntArray))).ToList():
Database.SqlQuery<int>(@"spProcedure1")).ToList();
示例显示如何不传递表参数
CREATE TYPE dbo.KeyIds]
AS TABLE(pkId int NOT NULL,
PRIMARY KEY CLUSTERED (pkId ASC)
WITH (IGNORE_DUP_KEY = OFF))
Go
-- ------------------------------
Create procedure testProc
@aIds dbo.keyIds readonly
as
Set NoCount On
if exists (select * from @aIds)
Select * from @aIds
else
Select 'No Aids passed in'
Go
-- ------------------------------
Exec dbo.testProc -- <--- Here I am NOT passing the @aids parameter
但即使我没有传递@aids参数
它仍然有效,子查询(select * from @aIds)
仍然起作用,并且因为它是一个空数据表,所以SP返回空消息'No Aids pass in'。
另一方面,如果您传递参数
Declare @MyIds dbo.keyIds
Insert @MyIds Values(1)
Insert @MyIds Values(2)
Insert @MyIds Values(3)
Insert @MyIds Values(4)
Insert @MyIds Values(5)
Exec dbo.testProc @MyIds -- <--- Here I AM passing the @aids parameter
它输出数据表参数的内容
C#代码示例......
public DataTable GetAccountTransactions(IEnumerable<int> accountIds)
{
const string procName = "FetchAccountTransactionData";
var acctIds = accountIds == null ?
new List<int>() : accountIds.ToList();
// -------------------------------------------------
var parms = DbParamList.Make();
// DbParamList is a List<IDbDataParameter>
// See here, ONLY ADD PARAMETER if list is NOT empty!
if (acctIds.Count > 0)
parms.AddSQLTableParm("aIds", acctIds);
try
{ // following constructs command obkect and calls SP
return Utilities.GetDataTable(schemaNm + "." +
procName, parms, copConn);
}
catch (SqlException dbX)
{
// Exception stuff
}
}
public class DbParamSortedList : SortedList<string,IDbDataParameter> { }
答案 1 :(得分:0)
替代解决方案
准备将List<int>
转换为dbo.IntArray
类型
public static DataTable IntArrayToDataTable(IEnumerable<int> ids)
{
if (ids == null)
return null;
DataTable table = new DataTable();
// datatable columns has to have same name as database type !
table.Columns.Add("IntValue", typeof(int));
foreach (int id in ids)
{
table.Rows.Add(id);
}
return table;
}
运行sql存储过程
var sqlParameters = new List<object>();
var parameter1 = Utils.IntArrayToDataTable(m.IntArray);
if (parameter1 != null)
sqlParameters.Add(new SqlParameter("intArray", parameter1)
// these variables are the key, without them it is not working
{
SqlDbType = SqlDbType.Structured,
TypeName = "dbo.IntArray"
});
else // parameter cannot be omitted !! even if all parameters are named !! otherwise parameter mismatch happens (in case of multiple parameters)
sqlParameters.Add(new SqlParameter("intArray", SqlDbType.Structured) { TypeName = "dbo.IntArray" });
var sqlQuery = "spProcedure1 @InArray";
return Database.SqlQuery<int>(sqlQuery, sqlParameters.ToArray()).ToList();