2009-07-09 10 views
3

Kennt jemand die beste Möglichkeit zum Erstellen einer SQL Server CE (Compact 3.5) -Tabelle auf der Grundlage des Schemas DataTable zur Laufzeit? Ich möchte nicht eine CREATE TABLE Anweisung basierend auf all den verschiedenen möglichen Datentypen schreiben müssen, usw.Programmgesteuert Erstellen einer SQL Server CE-Tabelle von DataTable

Als Bonus - wissen Sie dann, wie man es direkt aus einer Datentabelle ausfüllt?

Antwort

3

I kodiert, um eine vernünftige Lösung, aber hatte gehofft, dass case-Anweisungen für die SQL-Typen zu vermeiden:

Zum einen ein netter Trick von einem .NET-Typ in einem SqlDbType zu konvertieren:

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

Ein Fall Anweisung für die Typen für die Verwendung in SQL-Anweisungen:

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

Dann endlich die CREATE TABLE-Anweisung:

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

Nice! Aber wenn Sie eine leere DataTable oder mehrere Zeilen haben, funktioniert es nicht richtig. Ich habe den "DataRow-foreach" -Schlüssel durch eine Schleife im Schema ersetzt. Spalten und verwende die ColumnName- und MaxLength-Eigenschaften jeder Spalte. – Lars

+1

Sie erstellen jetzt auch Tabellen ohne ihre Identitätsspalteneinstellungen usw. Alles, was über einen FillSchema-Aufruf verfügbar ist, können Sie also dynamisch erstellen. –

4

ich verwendet habe, und der Code von Ben Breen aktualisiert:

  • GetSqlServerCETypeName Changed mit allen Arten arbeiten
  • Added eine Funktion fow Ganzes Dataset
  • und einige kleinere Verbesserungen

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

} 
Verwandte Themen