简体   繁体   English

C#auto生成SQL“用户自定义表类型”

[英]C# auto generate SQL “user-defined table type”

I have a question in regards to stored procedures taking a user defined table type as parameter. 关于将用户定义的表类型作为参数的存储过程,我有一个问题。 I know that I would just need to create a DataTable in c# code corresponding to the user defined table type in the SQL DB. 我知道我只需要在SQL DB中用户定义的表类型对应的c#代码中创建一个DataTable。 Just like here How to pass User Defined Table Type as Stored Procedured parameter in C# 就像这里如何在C#中将用户定义的表类型作为存储过程参数传递

However, what I would like to avoid is creating the DataTable manually in the code, but instead creating the DataTable automatically. 但是,我想避免的是在代码中手动创建DataTable,而是自动创建DataTable。 Is it somehow possible to get this from the database through a query ? 是否有可能通过查询从数据库中获取此信息?

If this isn't possible then another possibility is to get the definition of the user defined table type and then use this to automatically generate the DataTable. 如果这是不可能的,那么另一种可能性是获取用户定义的表类型的定义,然后使用它来自动生成DataTable。 But then the question is how do I get the definition of the type ? 但问题是我如何得到类型的定义?

Anybody got any solution to this problem, all examples I have found is generating the user-defined data type manually as DataTable in the code. 任何人都可以解决这个问题,我发现的所有例子都是在代码中手动生成用户定义的数据类型作为DataTable。

If you know the name of the table type, you should be able to execute the following piece of SQL: 如果您知道表类型的名称,则应该能够执行以下SQL:

declare @a dbo.TT
select * from @a

(Where dbo.TT is the name of the table type) (其中dbo.TT是表类型的名称)

This will generate an empty result set with all of the appropriate schema information (column names and types). 这将生成一个包含所有相应模式信息(列名和类型)的空结果集。 If you use that with a DataAdapter to populate a DataTable , you should be all set. 如果您使用DataAdapter填充DataTable ,则应该全部设置。

Try this (This is useful only for sending a stored proc a dataset of one column of values.) 试试这个(这仅用于向存储过程发送一列值的数据集。)

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

If you want a multi-column dataset (a multi-Column UDT in SQL Server) you will have to extend this, the signature would become: 如果需要多列数据集(SQL Server中的多列UDT),则必须对此进行扩展,签名将变为:

for three column dataset: 对于三列数据集:

public void AddSQLTableParm<T1, T2, T3>(
        string parmName, string typeName = "dbo.keyIds",
        IEnumerable<T1> value1s, 
        IEnumerable<T1> value2s, 
        IEnumerable<T1> value3s)
{ .... }

dbParamList defined : 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;
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM