Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从DataTable以编程方式创建SQL Server CE表_C#_.net_Sql Server_Sql Server Ce - Fatal编程技术网

C# 从DataTable以编程方式创建SQL Server CE表

C# 从DataTable以编程方式创建SQL Server CE表,c#,.net,sql-server,sql-server-ce,C#,.net,Sql Server,Sql Server Ce,有人知道在运行时基于DataTable的模式创建SQL Server CE(Compact 3.5)表的最佳方法吗?我不想基于所有不同的可能数据类型等,制定一个createtable语句 作为奖励,您知道如何直接从数据表中填充它吗?我编写了一个合理的解决方案,但希望避免SQL类型的case语句: 首先是一个从.NET类型转换为SqlDBType的巧妙技巧: /// <summary> /// Gets the correct SqlDBType for a given .NET ty

有人知道在运行时基于
DataTable
的模式创建SQL Server CE(Compact 3.5)表的最佳方法吗?我不想基于所有不同的可能数据类型等,制定一个
createtable
语句


作为奖励,您知道如何直接从数据表中填充它吗?

我编写了一个合理的解决方案,但希望避免SQL类型的case语句:

首先是一个从.NET类型转换为SqlDBType的巧妙技巧:

/// <summary>
/// Gets the correct SqlDBType for a given .NET type. Useful for working with SQL CE.
/// </summary>
/// <param name="type">The .Net Type used to find the SqlDBType.</param>
/// <returns>The correct SqlDbType for the .Net type passed in.</returns>
public static SqlDbType GetSqlDBTypeFromType(Type type)
{
    TypeConverter tc = TypeDescriptor.GetConverter(typeof(DbType));
    if (/*tc.CanConvertFrom(type)*/ true)
    {
        DbType dbType = (DbType)tc.ConvertFrom(type.Name);
        // A cheat, but the parameter class knows how to map between DbType and SqlDBType.
        SqlParameter param = new SqlParameter();
        param.DbType = dbType;
        return param.SqlDbType; // The parameter class did the conversion for us!!
    }
    else
    {
        throw new Exception("Cannot get SqlDbType from: " + type.Name);
    }
}
//
///获取给定.NET类型的正确SqlDBType。对于使用SQLCE非常有用。
/// 
///用于查找SqlDBType的.Net类型。
///传入的.Net类型的正确SqlDbType。
公共静态SqlDbType GetSqlDBTypeFromType(类型类型)
{
TypeConverter tc=TypeDescriptor.GetConverter(typeof(DbType));
if(/*tc.CanConvertFrom(type)*/true)
{
DbType DbType=(DbType)tc.ConvertFrom(type.Name);
//一个欺骗,但是参数类知道如何在DbType和SqlDBType之间映射。
SqlParameter param=新的SqlParameter();
param.DbType=DbType;
return param.SqlDbType;//参数类为我们做了转换!!
}
其他的
{
抛出新异常(“无法从:“+type.Name”获取SqlDbType);
}
}
SQL语句中使用的类型的case语句:

    /// <summary>
            /// The method gets the SQL CE type name for use in SQL Statements such as CREATE TABLE
            /// </summary>
            /// <param name="dbType">The SqlDbType to get the type name for</param>
            /// <param name="size">The size where applicable e.g. to create a nchar(n) type where n is the size passed in.</param>
            /// <returns>The SQL CE compatible type for use in SQL Statements</returns>
            public static string GetSqlServerCETypeName(SqlDbType dbType, int size)
            {
                // Conversions according to: http://msdn.microsoft.com/en-us/library/ms173018.aspx
                bool max = (size == int.MaxValue) ? true : false;
                bool over4k = (size > 4000) ? true : false;

                switch (dbType)
                {
                    case SqlDbType.BigInt:
                        return "bigint";
                    case SqlDbType.Binary:
                        return string.Format("binary ({0})", size);
                    case SqlDbType.Bit:
                        return "bit";
                    case SqlDbType.Char:
                        if (over4k) return "ntext";
                        else return string.Format("nchar({0})", size);
ETC...
//
///该方法获取SQL语句(如CREATE TABLE)中使用的SQL CE类型名称
/// 
///要获取其类型名称的SqlDbType
///适用的尺寸,例如创建nchar(n)类型,其中n是传入的尺寸。
///SQL语句中使用的SQL CE兼容类型
公共静态字符串GetSqlServerCETypeName(SqlDbType dbType,int size)
{
//转换依据:http://msdn.microsoft.com/en-us/library/ms173018.aspx
bool max=(size==int.MaxValue)?真:假;
bool over4k=(大小>4000)?真:假;
开关(dbType)
{
案例SqlDbType.BigInt:
返回“bigint”;
案例SqlDbType.Binary:
返回string.Format(“二进制({0})”,大小);
案例SqlDbType.Bit:
返回“位”;
案例SqlDbType.Char:
如果(超过4K)返回“ntext”;
else返回string.Format(“nchar({0})”,size);
等
最后是CREATETABLE语句:

    /// <summary>
    /// Genenerates a SQL CE compatible CREATE TABLE statement based on a schema obtained from
    /// a SqlDataReader or a SqlCeDataReader.
    /// </summary>
    /// <param name="tableName">The name of the table to be created.</param>
    /// <param name="schema">The schema returned from reader.GetSchemaTable().</param>
    /// <returns>The CREATE TABLE... Statement for the given schema.</returns>
    public static string GetCreateTableStatement(string tableName, DataTable schema)
    {
        StringBuilder builder = new StringBuilder();
        builder.Append(string.Format("CREATE TABLE [{0}] (\n", tableName));

        foreach (DataRow row in schema.Rows)
        {
            string typeName = row["DataType"].ToString();
            Type type = Type.GetType(typeName);

            string name = (string)row["ColumnName"];
            int size = (int)row["ColumnSize"];

            SqlDbType dbType = GetSqlDBTypeFromType(type);

            builder.Append(name);
            builder.Append(" ");
            builder.Append(GetSqlServerCETypeName(dbType, size));
            builder.Append(", ");
        }

        if (schema.Rows.Count > 0) builder.Length = builder.Length - 2;

        builder.Append("\n)");
        return builder.ToString();
    }
//
///根据从中获取的架构生成与SQL CE兼容的CREATE TABLE语句
///SqlDataReader或SqlCeDataReader。
/// 
///要创建的表的名称。
///从reader.GetSchemaTable()返回的架构。
///给定架构的CREATETABLE…语句。
公共静态字符串GetCreateTableStatement(字符串表名、数据表架构)
{
StringBuilder=新的StringBuilder();
Append(string.Format(“创建表[{0}](\n”,tableName));
foreach(schema.Rows中的数据行)
{
字符串类型名称=行[“数据类型”]。ToString();
Type Type=Type.GetType(typeName);
字符串名称=(字符串)行[“ColumnName”];
int size=(int)行[“ColumnSize”];
SqlDbType dbType=GetSqlDBTypeFromType(type);
builder.Append(名称);
生成器。追加(“”);
Append(GetSqlServerCETypeName(dbType,size));
生成器。追加(“,”);
}
如果(schema.Rows.Count>0)builder.Length=builder.Length-2;
builder.Append(“\n)”);
返回builder.ToString();
}

我使用并更新了Ben Breen的代码:

  • 已将GetSqlServerCETypeName更改为与所有类型一起使用
  • 为整个数据集添加了一个函数
  • 还有一些小的调整
GetSqlDBTypeFromType

/// <summary>
    /// Gets the correct SqlDBType for a given .NET type. Useful for working with SQL CE.
    /// </summary>
    /// <param name="type">The .Net Type used to find the SqlDBType.</param>
    /// <returns>The correct SqlDbType for the .Net type passed in.</returns>
    public static SqlDbType GetSqlDBTypeFromType(Type type)
    {
        TypeConverter tc = TypeDescriptor.GetConverter(typeof(DbType));
        if (/*tc.CanConvertFrom(type)*/ true)
        {
            DbType dbType = (DbType)tc.ConvertFrom(type.Name);
            // A cheat, but the parameter class knows how to map between DbType and SqlDBType.
            SqlCeParameter param = new SqlCeParameter();
            param.DbType = dbType;
            return param.SqlDbType; // The parameter class did the conversion for us!!
        }
        else
        {
            throw new Exception("Cannot get SqlDbType from: " + type.Name);
        }
    }

对于那些希望在常规SQL Server设置(非CE)上执行此操作的用户,我已设法修改此设置,以便在需要基于巨大csv文件(使用4.7.1.NET框架)以编程方式创建数据库表时使用SQL Server 2016设置。 请注意,这会检查最大列数,但不会检查最大行数,因此如果在处理大型csv文件时不考虑这一点,您可能会遇到错误

using System.Data;
using System.Data.SqlClient;
using System.ComponentModel;
//
//
//
        private static DataTable GetDataTabletFromCSVFile(string csv_file_path)
        {
            DataTable csvData = new DataTable();
            try
            {
                using (TextFieldParser csvReader = new TextFieldParser(csv_file_path))
                {
                    csvReader.TextFieldType = FieldType.Delimited;
                    csvReader.SetDelimiters(new string[] { "," });
                    csvReader.HasFieldsEnclosedInQuotes = false;
                    string[] colFields = csvReader.ReadFields();
                    int columnCounter = 0;

                    foreach (string column in colFields)
                    {
                        if (columnCounter > 1023)
                        {
                            break; // the table has reached the maximum column size, either ignore the extra columns, or create additional linked tables (sounds like awful table design though).
                        }
                        DataColumn datecolumn = new DataColumn(column);
                        datecolumn.AllowDBNull = true;
                        csvData.Columns.Add(datecolumn);
                        columnCounter++;
                    }
                    while (!csvReader.EndOfData)
                    {
                        string[] fieldData = csvReader.ReadFields();
                        Array.Resize(ref fieldData, 1024);   //max number of columns is 1024 in SQL table, and we're not going through the trouble of making a Sparse table.
                        //Making empty value as null
                        for (int i = 0; i < fieldData.Length; i++)
                        {
                            if (fieldData[i] == "")
                            {
                                fieldData[i] = null;
                            }
                        }
                        csvData.Rows.Add(fieldData);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return csvData;
        }

        /** <summary>
        * Gets the correct SqlDBType for a given .NET type. Useful for working with SQL.
        * </summary>
        * <param name="type">The .Net Type used to find the SqlDBType.</param>
        * <returns>The correct SqlDbType for the .Net type passed in.</returns>
        */
        public static SqlDbType GetSqlDBTypeFromType(Type type)
        {
            TypeConverter tc = TypeDescriptor.GetConverter(typeof(DbType));

            DbType dbType = (DbType)tc.ConvertFrom(type.Name);
            // A cheat, but the parameter class knows how to map between DbType and SqlDBType.
            SqlParameter param = new SqlParameter();
            param.DbType = dbType;

            return param.SqlDbType; // The parameter class did the conversion for us!!

        }

        /**
        * <summary>
        * The method gets the SQL type name for use in SQL Statements such as CREATE TABLE
        * </summary>
        * <param name="dbType">The SqlDbType to get the type name for</param>
        * <param name="size">The size where applicable e.g. to create a nchar(n) type where n is the size passed in.</param>
        * <returns>A string of the SQL compatible type for use in SQL Statements</returns>
        */
        public static string GetSqlServerTypeName(SqlDbType dbType, int size)
        {
            // Conversions according to: https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-data-type-mappings
            bool max = (size == int.MaxValue || size == -1) ? true : false;
            string returnVal = "";

            if (max)
            {
                returnVal = Enum.GetName(typeof(SqlDbType), dbType) + " (max)";
            }
            else if (size > 0)
            {
                returnVal = string.Format(Enum.GetName(typeof(SqlDbType), dbType) + " ({0})", size);
            }
            else
            {
                returnVal = Enum.GetName(typeof(SqlDbType), dbType);
            }

            return returnVal;
        }

        /**
         * <summary>
        * Genenerates a SQL compatible CREATE TABLE statement based on a schema obtained from
        * a SqlDataTable.
        * </summary>
        * <param name="table">The name of the table to be created.</param>
        * <returns>The CREATE TABLE... Statement for the given data table.</returns>
        */
        public static string GetCreateTableStatement(DataTable table)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(string.Format("CREATE TABLE [{0}] (", table.TableName));
            int primaryCol = 0;

            foreach (DataColumn col in table.Columns)
            {
                SqlDbType dbType = GetSqlDBTypeFromType(col.DataType);
                builder.Append("[");
                builder.Append(col.ColumnName);
                builder.Append("]");
                builder.Append(" ");
                builder.Append(GetSqlServerTypeName(dbType, col.MaxLength));
                //if on first column, assume it's a "PRIMARY KEY" (for now)
                if(primaryCol == 0)
                {
                    builder.Append(" PRIMARY KEY");
                }
                builder.Append(", ");
                primaryCol++;
            }

            if (table.Columns.Count > 0) builder.Length = builder.Length - 2;

            builder.Append(")");
            return builder.ToString();
        }


        /**
         * <summary>
        * Genenerates a SQL compatible CREATE TABLE statement based on a schema obtained from
        * a SqlDataTable.
        * </summary>
        * <param name="dtable">The name of the table to be created.</param>
        * <param name="conn">The SQL Connection to the database that the table will be created in.</param>
         */
        public static void CreateFromDataTable(DataTable dTable, SqlConnection conn)
        {
            bool openedHere = false;
            if (conn.State == ConnectionState.Closed)
            {
                conn.Open();
                openedHere = true;
            }
            SqlCommand cmd;

            string createSql = GetCreateTableStatement(dTable);
            Console.WriteLine(createSql);

            cmd = new SqlCommand(createSql, conn);
            Console.WriteLine(cmd.ExecuteNonQuery());

            if (openedHere)
            {
                conn.Close();
            }
        }
使用系统数据;
使用System.Data.SqlClient;
使用系统组件模型;
//
//
//
私有静态数据表GetDataTabletFromCSVFile(字符串csv\u文件\u路径)
{
DataTable csvData=新DataTable();
尝试
{
使用(TextFieldParser csvReader=新的TextFieldParser(csv_文件_路径))
{
csvReader.TextFieldType=FieldType.Delimited;
SetDelimiters(新字符串[]{“,”});
csvReader.HasFieldsEnclosedInQuotes=false;
字符串[]colFields=csvReader.ReadFields();
int columnCounter=0;
foreach(colFields中的字符串列)
{
如果(列计数器>1023)
{
break;//表已达到最大列大小,请忽略额外的列,或创建额外的链接表(尽管听起来像糟糕的表设计)。
}
DataColumn datecolumn=新的DataColumn(列);
datecolumn.AllowDBNull=true;
csvData.Columns.Add(datecolumn);
列计数器++;
}
而(!csvReader.EndOfData)
{
字符串[]fieldData=csvReader.ReadFields();
A.
/// <summary>
    /// Genenerates a SQL CE compatible CREATE TABLE statement based on a schema obtained from
    /// a SqlDataReader or a SqlCeDataReader.
    /// </summary>
    /// <param name="tableName">The name of the table to be created.</param>
    /// <param name="schema">The schema returned from reader.GetSchemaTable().</param>
    /// <returns>The CREATE TABLE... Statement for the given schema.</returns>
    public static string GetCreateTableStatement(DataTable table)
    {
        StringBuilder builder = new StringBuilder();
        builder.Append(string.Format("CREATE TABLE [{0}] (", table.TableName));

        foreach (DataColumn col in table.Columns)
        {
            SqlDbType dbType = GetSqlDBTypeFromType(col.DataType);
            builder.Append("[");
            builder.Append(col.ColumnName);
            builder.Append("]");
            builder.Append(" ");
            builder.Append(GetSqlServerCETypeName(dbType, col.MaxLength));
            builder.Append(", ");
        }

        if (table.Columns.Count > 0) builder.Length = builder.Length - 2;

        builder.Append(")");
        return builder.ToString();
    }
public static void CreateFromDataset(DataSet set, SqlCeConnection conn)
    {
        conn.Open();
        SqlCeCommand cmd;
        foreach (DataTable table in set.Tables)
        {
            string createSql = copyDB.GetCreateTableStatement(table);
            Console.WriteLine(createSql);

            cmd = new SqlCeCommand(createSql, conn);
            Console.WriteLine(cmd.ExecuteNonQuery());
        }
        conn.Close();
    }

}
using System.Data;
using System.Data.SqlClient;
using System.ComponentModel;
//
//
//
        private static DataTable GetDataTabletFromCSVFile(string csv_file_path)
        {
            DataTable csvData = new DataTable();
            try
            {
                using (TextFieldParser csvReader = new TextFieldParser(csv_file_path))
                {
                    csvReader.TextFieldType = FieldType.Delimited;
                    csvReader.SetDelimiters(new string[] { "," });
                    csvReader.HasFieldsEnclosedInQuotes = false;
                    string[] colFields = csvReader.ReadFields();
                    int columnCounter = 0;

                    foreach (string column in colFields)
                    {
                        if (columnCounter > 1023)
                        {
                            break; // the table has reached the maximum column size, either ignore the extra columns, or create additional linked tables (sounds like awful table design though).
                        }
                        DataColumn datecolumn = new DataColumn(column);
                        datecolumn.AllowDBNull = true;
                        csvData.Columns.Add(datecolumn);
                        columnCounter++;
                    }
                    while (!csvReader.EndOfData)
                    {
                        string[] fieldData = csvReader.ReadFields();
                        Array.Resize(ref fieldData, 1024);   //max number of columns is 1024 in SQL table, and we're not going through the trouble of making a Sparse table.
                        //Making empty value as null
                        for (int i = 0; i < fieldData.Length; i++)
                        {
                            if (fieldData[i] == "")
                            {
                                fieldData[i] = null;
                            }
                        }
                        csvData.Rows.Add(fieldData);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return csvData;
        }

        /** <summary>
        * Gets the correct SqlDBType for a given .NET type. Useful for working with SQL.
        * </summary>
        * <param name="type">The .Net Type used to find the SqlDBType.</param>
        * <returns>The correct SqlDbType for the .Net type passed in.</returns>
        */
        public static SqlDbType GetSqlDBTypeFromType(Type type)
        {
            TypeConverter tc = TypeDescriptor.GetConverter(typeof(DbType));

            DbType dbType = (DbType)tc.ConvertFrom(type.Name);
            // A cheat, but the parameter class knows how to map between DbType and SqlDBType.
            SqlParameter param = new SqlParameter();
            param.DbType = dbType;

            return param.SqlDbType; // The parameter class did the conversion for us!!

        }

        /**
        * <summary>
        * The method gets the SQL type name for use in SQL Statements such as CREATE TABLE
        * </summary>
        * <param name="dbType">The SqlDbType to get the type name for</param>
        * <param name="size">The size where applicable e.g. to create a nchar(n) type where n is the size passed in.</param>
        * <returns>A string of the SQL compatible type for use in SQL Statements</returns>
        */
        public static string GetSqlServerTypeName(SqlDbType dbType, int size)
        {
            // Conversions according to: https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-data-type-mappings
            bool max = (size == int.MaxValue || size == -1) ? true : false;
            string returnVal = "";

            if (max)
            {
                returnVal = Enum.GetName(typeof(SqlDbType), dbType) + " (max)";
            }
            else if (size > 0)
            {
                returnVal = string.Format(Enum.GetName(typeof(SqlDbType), dbType) + " ({0})", size);
            }
            else
            {
                returnVal = Enum.GetName(typeof(SqlDbType), dbType);
            }

            return returnVal;
        }

        /**
         * <summary>
        * Genenerates a SQL compatible CREATE TABLE statement based on a schema obtained from
        * a SqlDataTable.
        * </summary>
        * <param name="table">The name of the table to be created.</param>
        * <returns>The CREATE TABLE... Statement for the given data table.</returns>
        */
        public static string GetCreateTableStatement(DataTable table)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(string.Format("CREATE TABLE [{0}] (", table.TableName));
            int primaryCol = 0;

            foreach (DataColumn col in table.Columns)
            {
                SqlDbType dbType = GetSqlDBTypeFromType(col.DataType);
                builder.Append("[");
                builder.Append(col.ColumnName);
                builder.Append("]");
                builder.Append(" ");
                builder.Append(GetSqlServerTypeName(dbType, col.MaxLength));
                //if on first column, assume it's a "PRIMARY KEY" (for now)
                if(primaryCol == 0)
                {
                    builder.Append(" PRIMARY KEY");
                }
                builder.Append(", ");
                primaryCol++;
            }

            if (table.Columns.Count > 0) builder.Length = builder.Length - 2;

            builder.Append(")");
            return builder.ToString();
        }


        /**
         * <summary>
        * Genenerates a SQL compatible CREATE TABLE statement based on a schema obtained from
        * a SqlDataTable.
        * </summary>
        * <param name="dtable">The name of the table to be created.</param>
        * <param name="conn">The SQL Connection to the database that the table will be created in.</param>
         */
        public static void CreateFromDataTable(DataTable dTable, SqlConnection conn)
        {
            bool openedHere = false;
            if (conn.State == ConnectionState.Closed)
            {
                conn.Open();
                openedHere = true;
            }
            SqlCommand cmd;

            string createSql = GetCreateTableStatement(dTable);
            Console.WriteLine(createSql);

            cmd = new SqlCommand(createSql, conn);
            Console.WriteLine(cmd.ExecuteNonQuery());

            if (openedHere)
            {
                conn.Close();
            }
        }