关于将用户定义的表类型作为参数的存储过程,我有一个问题。我知道我只需要在SQL DB中用户定义的表类型对应的c#代码中创建一个DataTable。就像这里一样 How to pass User Defined Table Type as Stored Procedured parameter in C#
但是,我想避免的是在代码中手动创建DataTable,而是自动创建DataTable。是否有可能通过查询从数据库中获取此信息?
如果这不可能,那么另一种可能性是获取用户定义的表类型的定义,然后使用它来自动生成DataTable。但问题是如何获得类型的定义?
任何人都能解决这个问题,我发现的所有例子都是在代码中手动生成用户定义的数据类型。
答案 0 :(得分:5)
如果您知道表类型的名称,则应该能够执行以下SQL:
declare @a dbo.TT
select * from @a
(其中dbo.TT
是表类型的名称)
这将生成一个包含所有相应模式信息(列名和类型)的空结果集。如果您使用DataAdapter
来填充DataTable
,则应该全部设置。
答案 1 :(得分:0)
尝试此操作(这仅适用于向存储过程发送一列值的数据集。)
public void AddSQLTableParm<T>(string parmName,
IEnumerable<T> values,
string typeName = "dbo.keyIds") // <== here put SQL Server UDT Type neame
{
var parm = new SqlParameter(parmName,
DbParamList.CreateDataTable(values))
{
SqlDbType = SqlDbType.Structured,
TypeName = typeName
};
Add(parmName, parm);
}
如果您需要多列数据集(SQL Server中的多列UDT),则必须对此进行扩展,签名将变为:
用于三列数据集:
public void AddSQLTableParm<T1, T2, T3>(
string parmName, string typeName = "dbo.keyIds",
IEnumerable<T1> value1s,
IEnumerable<T1> value2s,
IEnumerable<T1> value3s)
{ .... }
dbParamList定义:
public class DbParamList : List<IDbDataParameter>
{
private DbParamList() {}
public static DbParamList Make(IEnumerable<SqlParameter> parms)
{
var prmLst = new DbParamList();
prmLst.AddRange(parms);
return prmLst;
}
public static DbParamList Make(params SqlParameter[] parms)
{
var prmLst = new DbParamList();
prmLst.AddRange(parms);
return prmLst;
}
public void AddSQLParm(string parmName, bool value)
{ Add(new SqlParameter(parmName, value ? "1" : "0")); }
public void AddSQLParm(string parmName, bool? value)
{
if (!value.HasValue)
{
throw new ArgumentNullException(
"Null value passed to AddSQLParm<>()");
}
Add(new SqlParameter(parmName, value.Value ? "1" : "0"));
}
public void AddSQLParm<T>(string parmName, T value)
{
var type = typeof(T);
if (type.IsEnum) Add(new SqlParameter(parmName,
Convert.ChangeType(value, Enum.GetUnderlyingType(type))));
else Add(new SqlParameter(parmName, value));
}
public void AddSQLParm<T>(string parmName, T? value,
bool ignoreNull = false) where T : struct
{
var type = typeof(T);
if (!value.HasValue)
{
if (ignoreNull) return;
throw new ArgumentNullException(
"Null value passed to AddSQLParm<>()");
}
// ---------------------------------------
if (type.IsEnum) Add(new SqlParameter(parmName,
Convert.ChangeType(value.Value, Enum.GetUnderlyingType(type))));
else Add(new SqlParameter(parmName, value.Value));
}
public void AddSQLTableParm<T>(string parmName, IEnumerable<T> values)
{
var parm = new SqlParameter(parmName, CreateDataTable(values))
{
SqlDbType = SqlDbType.Structured,
TypeName = "dbo.keyIds"
};
Add(parm);
}
internal static DataTable CreateDataTable<T>(IEnumerable<T> values)
{
var dt = new DataTable();
var props = typeof (T).GetProperties();
if (props.Length > 0)
{
foreach (var col in props)
dt.Columns.Add(col.Name, col.PropertyType);
foreach (var id in values)
{
var newRow = dt.NewRow();
foreach (var prop in id.GetType().GetProperties())
newRow[prop.Name] = prop.GetValue(id, null);
dt.Rows.Add(newRow);
}
}
else
{
dt.Columns.Add("ids");
foreach (var id in values) dt.Rows.Add(id);
}
return dt;
}
}