8

The only references I can find is someone suggesting to use Entity Framework 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.

This doesn't have to be TSQL/MSSQL (2014) Compatible but that's my DBMS.

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.

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.

        var columnNames = GetColumnsToBeUpdated<T>().ToList();
        var columnTypes = GetColumnsTypesToBeUpdated<T>().ToList();


        var selects = columnNames.Select((t, i) => $"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 && type.GetGenericTypeDefinition() == typeof(Nullable<>))
        {
            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<string> GetColumnsToBeUpdated<T>() where T : class, new()
    {
        var typeT = new T();
        var ps = typeT.GetType().GetProperties();
        var propertyNames = ps.Select(p => p.Name);

        return propertyNames.Except(GetColumnsToBeIgnored<T>());
    }

    private static IEnumerable<string> GetColumnsTypesToBeUpdated<T>() where T : class, new()
    {
        var typeT = new T();
        var ps = typeT.GetType().GetProperties();
        return ps.Select(p => p.PropertyType).Select(GetSqlDataType).ToList();
    }

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.

Community
  • 1
  • 1
LearningJrDev
  • 911
  • 2
  • 8
  • 27
  • Figuring out how to map a simple type to a brand new DB table is a fairly trivial task. How you're going to handle 1) tables that already have data 2) synchronizing your class and tables 3) deploy your structures to various environments 4) deal with POCO's that aren't easily mapped 5) handle various database constraints are the reason why this isn't a reasonable question. Perhaps you should consider a NoSQL route – Conrad Frix Apr 21 '17 at 21:40
  • 1) that could easily be an input to the creator 2) not needed 3) not needed 4) not a requirement, simple pocos only 5) C# tries its best, if SQL cant do it then it cant do it. I am not looking for an enterprise solution, but something that is straight forward and easy to read while still giving functionality. – LearningJrDev Apr 21 '17 at 22:36
  • I think you missed my point. Solving the trivial case isn't worthwhile – Conrad Frix Apr 21 '17 at 22:43
  • Possible duplicate: [stackoverflow.com/.../how-can-i-generate-database-tables-from-c-sharp-classes](https://stackoverflow.com/q/47239/7794769) – stomy Aug 02 '19 at 04:10

1 Answers1

10

You can convert the C# class to Json and then convert the Json to Sql.

Convert C# class to Json:

Convert Json to SQL online:

stomy
  • 1,778
  • 1
  • 15
  • 16
  • cshar2json.io and sqlify.io have certificate problems. https://www.jsonutils.com/ gives a 404 – Luuk Jul 09 '22 at 15:58
  • Working websites for C# to JSON : https://class2json.net/, for JSON to Sql : https://www.convertjson.com/json-to-sql.htm – nmariot May 15 '23 at 20:25