2009-07-09 75 views
3

有誰知道在運行時基於DataTable的架構創建SQL Server CE(Compact 3.5)表的最佳方式嗎?我不想根據所有不同的可能數據類型制定CREATE TABLE聲明等。以編程方式從DataTable創建SQL Server CE表

作爲一個獎勵 - 你知道如何直接從數據表中填寫它嗎?

回答

3

我編寫了一個合理的解決方案,但希望避免對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); 
    } 
} 

的情況聲明的類型使用SQL語句:

/// <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... 

後來終於CREATE TABLE語句:

/// <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(); 
    } 
+1

不錯!但是當你有一個空的DataTable或多行時,它不能正常工作。我用schema.Columns上的循環替換了「DataRow-foreach」-loop,並使用每列的ColumnName-和MaxLength-屬性。 – Lars 2009-07-29 14:34:44

4

我已經使用和更新將代碼從本·布林:

  • 改變GetSqlServerCETypeName各類
  • 新增FOW一個整個數據集
  • 而一些小的調整功能工作

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

GetSqlServerCETypeName

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

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

GetCreateTableStatement

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

CreateFromDataset

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

} 
相關問題