c#自动生成SQL“用户定义的表类型”

本文关键字:类型 定义 用户 自动生成 SQL | 更新日期: 2023-09-27 18:03:02

关于以用户定义的表类型作为参数的存储过程,我有一个问题。我知道我只需要在c#代码中创建一个DataTable,对应于SQL DB中用户定义的表类型。就像这里c#中如何传递用户定义表类型作为存储过程参数

然而,我想避免的是在代码中手动创建数据表,而是自动创建数据表。是否有可能通过查询从数据库中获取此信息?

如果这是不可能的,那么另一种可能性是获取用户定义的表类型的定义,然后使用它来自动生成DataTable。但问题是如何得到类型的定义呢?

任何人得到这个问题的任何解决方案,我发现的所有例子都是在代码中手动生成用户定义的数据类型为DataTable。

c#自动生成SQL“用户定义的表类型”

如果您知道表类型的名称,您应该能够执行以下SQL代码:

declare @a dbo.TT
select * from @a

(其中dbo.TT为表类型的名称)

这将生成一个包含所有适当模式信息(列名和类型)的空结果集。如果你用DataAdapter来填充DataTable,你应该都设置好了。

试试这个(这只对向存储过程发送一列值的数据集有用)

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 defined:

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;
    }
}