title: Convert C# Class to SQL table
body: <p>The only references I can find is someone <a href="https://stackoverflow.com/questions/3405087/convert-c-sharp-classes-class-library-to-sql-ddl-tables">suggesting to use Entity Framework</a> to do this, but I don't have or use Entity Framework. The only other thing on this subject is going from SQL table to C# class, which is the opposite of what I want.</p>
  
  <p>This doesn't have to be TSQL/MSSQL (2014) Compatible but that's my DBMS.</p>
  
  <p>The C# class is just a POCO. I think I heard you could take the class and somehow convert it a DataTable and then using SqlBulkCopy have it create a table from the DataTable.</p>
  
  <p>This is what I am currently using it uses a SELECT INTO and casting a null to a sqlType to make nullable columns. As you can see it's quite raw but gets the job done mostly - I am looking for less error prone methods.</p>
  
  <pre><code>        var columnNames = GetColumnsToBeUpdated&lt;T&gt;().ToList();
          var columnTypes = GetColumnsTypesToBeUpdated&lt;T&gt;().ToList();
  
  
          var selects = columnNames.Select((t, i) =&gt; $"CAST(NULL as {columnTypes[i]}) AS [{t}]");
  
          var createsql = $@"
              SELECT {string.Join(", ", selects)}
              INTO SDE.[{tableName}]";
  
          using (var connection = new SqlConnection(_sdeConnectionString))
          {
              EsriServer.ExecuteNonQuery(connection, $"IF OBJECT_ID(N'SDE.[{tableName}]', N'U') IS NOT NULL " +
                                                     $"DROP TABLE SDE.[{tableName}]", null);
              EsriServer.ExecuteNonQuery(connection, createsql, null);
              EsriServer.ExecuteNonQuery(connection, $"TRUNCATE TABLE SDE.[{tableName}]", null);
          }
  
      private static string GetSqlDataType(Type type)
      {
          var name = type.Name;
          if (type.IsGenericType &amp;&amp; type.GetGenericTypeDefinition() == typeof(Nullable&lt;&gt;))
          {
              name = type.GetGenericArguments()[0].Name;
          }
  
          switch (name)
          {
              case "Guid":
                  return "uniqueidentifier";
              case "Boolean":
                  return "bit";
              case "Byte":
                  return "tinyint";
              case "Int16":
                  return "smallint";
              case "Int32":
                  return "int";
              case "Int64":
                  return "bigint";
              case "Decimal":
                  return "decimal(38,25)";
              case "Single":
                  return "real";
              case "Double":
                  return "float";
              case "DateTime":
                  return "datetime";
              case "String":
              case "Char[]":
                  return "nvarchar(max)";
              case "Char":
                  return "nvarchar(1)";
              case "Byte[]":
                  return "varbinary";
              case "Object":
                  return "sql_variant";
              default:
                  throw new ArgumentOutOfRangeException();
          }
      }
  
      private static IEnumerable&lt;string&gt; GetColumnsToBeUpdated&lt;T&gt;() where T : class, new()
      {
          var typeT = new T();
          var ps = typeT.GetType().GetProperties();
          var propertyNames = ps.Select(p =&gt; p.Name);
  
          return propertyNames.Except(GetColumnsToBeIgnored&lt;T&gt;());
      }
  
      private static IEnumerable&lt;string&gt; GetColumnsTypesToBeUpdated&lt;T&gt;() where T : class, new()
      {
          var typeT = new T();
          var ps = typeT.GetType().GetProperties();
          return ps.Select(p =&gt; p.PropertyType).Select(GetSqlDataType).ToList();
      }
  </code></pre>
  
  <p>If this can't be done accurately or requires major code then I am pretty fine with an application or online server that lets me paste in a simple C# class and get back a create table statement.</p>