2009-07-09 18 views
3

実行時にDataTableのスキーマに基づいてSQL Server CE(Compact 3.5)テーブルを作成する最良の方法を知っている人はいますか?私はCREATE TABLEステートメントを可能なすべてのデータ型に基づいて定式化する必要はありません。DataTableからSQL Server CEテーブルをプログラムで作成する

これは、データテーブルから直接入力する方法を知っていますか?

答えて

3

私は合理的な解決策をコード化されますが、SQLの種類のcase文を避けるために期待していた。第一

なSQLDbTypeに.NET型から変換するために巧妙なトリック:

/// <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または複数の行がある場合、正しく動作しません。私は "DataRow-foreach" -loopをschema.Columnsのループに置き換え、各列のColumnName-とMaxLength-プロパティを使用しました。 – Lars

+1

また、ID列の設定などがないテーブルも作成しています.FillSchemaの呼び出しですべて利用できるので、動的にビルドすることができます。 –

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(); 
        } 
    
    } 
    
  • 関連する問題