una qué que programacion objetos objeto herencia form estructura ejemplos datos clases clase c# code-generation data-access
aquí

qué - ¿Cómo puedo generar tablas de base de datos de clases de C#?



que es una clase en programacion (13)

@Jonathan Holland

Wow, creo que es el trabajo más crudo que he visto poner en una publicación de StackOverflow. Bien hecho. Sin embargo , en lugar de construir sentencias DDL como cadenas, definitivamente debe usar las clases de objetos de administración de SQL Server introducidas con SQL 2005.

David Hayden tiene una publicación titulada Crear tabla en SQL Server 2005 usando C # y SQL Server Management Objects (SMO) - Generación de código que describe cómo crear una tabla usando SMO. Los objetos fuertemente tipados lo convierten en una brisa con métodos como:

// Create new table, called TestTable Table newTable = new Table(db, "TestTable");

y

// Create a PK Index for the table Index index = new Index(newTable, "PK_TestTable"); index.IndexKeyType = IndexKeyType.DriPrimaryKey;

VanOrman, si está utilizando SQL 2005, definitivamente haga de SMO parte de su solución.

¿Alguien sabe una manera de autogenerar tablas de bases de datos para una clase determinada? No estoy buscando una capa de persistencia completa. Ya tengo una solución de acceso a datos que estoy usando, pero de repente tengo que almacenar mucha información de un gran número de clases y realmente no quiero tener que crear todas estas tablas a mano. Por ejemplo, dada la siguiente clase:

class Foo { private string property1; public string Property1 { get { return property1; } set { property1 = value; } } private int property2; public int Property2 { get { return property2; } set { property2 = value; } } }

Esperaría el siguiente SQL:

CREATE TABLE Foo ( Property1 VARCHAR(500), Property2 INT )

También me pregunto cómo podría manejar tipos complejos. Por ejemplo, en la clase citada anteriormente, si cambiamos eso por ser:

class Foo { private string property1; public string Property1 { get { return property1; } set { property1 = value; } } private System.Management.ManagementObject property2; public System.Management.ManagementObject Property2 { get { return property2; } set { property2 = value; } } }

¿Cómo podría manejar esto?

He tratado de autogenerar las secuencias de comandos de la base de datos utilizando la reflexión para enumerar las propiedades de cada clase, pero es complicado y los tipos de datos complejos me han dejado perplejo.


@PortMan,

Los SQL DataObjects son geniales, no estaba al tanto de ellos. Eso definitivamente eliminaría parte del trabajo de mi código.

En realidad, mi código original era mucho más ordenado y estaba distribuido en 3 clases, pero después de que funcionó, decidí fusionarlo todo en una sola pasta para aquí.

Consideraría agregar un atributo [SqlTable] a las clases de dominio, así como [PrimaryKey] a la clave de ID principal, en lugar de hacer que el código genere automáticamente una ID.

Al hacer eso, el código podría ubicar adecuadamente las restricciones de PK, Index y FK en las columnas correctas.

Sin embargo, VanOrMan probablemente podría usar mi código como está para generar el 99% de lo que necesita y luego simplemente ajustar el SQL en un editor antes de ejecutarlo.


Además ... tal vez puedas usar alguna herramienta como Visio (no estoy seguro si Visio hace esto, pero creo que sí) para aplicar ingeniería inversa a tus clases en UML y luego usar el UML para generar el Esquema DB ... o tal vez usar una herramienta como esta http://www.tangiblearchitect.net/visual-studio/


Creo que para tipos de datos complejos, debe ampliarlos especificando un método ToDB () que contenga su propia implementación para crear tablas en el DB, y de esta manera se vuelve auto-recursivo.


Es muy tarde, y solo pasé unos 10 minutos en esto, así que es extremadamente descuidado, sin embargo funciona y te dará un buen punto de partida:

using System; using System.Collections.Generic; using System.Text; using System.Reflection; namespace TableGenerator { class Program { static void Main(string[] args) { List<TableClass> tables = new List<TableClass>(); // Pass assembly name via argument Assembly a = Assembly.LoadFile(args[0]); Type[] types = a.GetTypes(); // Get Types in the assembly. foreach (Type t in types) { TableClass tc = new TableClass(t); tables.Add(tc); } // Create SQL for each table foreach (TableClass table in tables) { Console.WriteLine(table.CreateTableScript()); Console.WriteLine(); } // Total Hacked way to find FK relationships! Too lazy to fix right now foreach (TableClass table in tables) { foreach (KeyValuePair<String, Type> field in table.Fields) { foreach (TableClass t2 in tables) { if (field.Value.Name == t2.ClassName) { // We have a FK Relationship! Console.WriteLine("GO"); Console.WriteLine("ALTER TABLE " + table.ClassName + " WITH NOCHECK"); Console.WriteLine("ADD CONSTRAINT FK_" + field.Key + " FOREIGN KEY (" + field.Key + ") REFERENCES " + t2.ClassName + "(ID)"); Console.WriteLine("GO"); } } } } } } public class TableClass { private List<KeyValuePair<String, Type>> _fieldInfo = new List<KeyValuePair<String, Type>>(); private string _className = String.Empty; private Dictionary<Type, String> dataMapper { get { // Add the rest of your CLR Types to SQL Types mapping here Dictionary<Type, String> dataMapper = new Dictionary<Type, string>(); dataMapper.Add(typeof(int), "BIGINT"); dataMapper.Add(typeof(string), "NVARCHAR(500)"); dataMapper.Add(typeof(bool), "BIT"); dataMapper.Add(typeof(DateTime), "DATETIME"); dataMapper.Add(typeof(float), "FLOAT"); dataMapper.Add(typeof(decimal), "DECIMAL(18,0)"); dataMapper.Add(typeof(Guid), "UNIQUEIDENTIFIER"); return dataMapper; } } public List<KeyValuePair<String, Type>> Fields { get { return this._fieldInfo; } set { this._fieldInfo = value; } } public string ClassName { get { return this._className; } set { this._className = value; } } public TableClass(Type t) { this._className = t.Name; foreach (PropertyInfo p in t.GetProperties()) { KeyValuePair<String, Type> field = new KeyValuePair<String, Type>(p.Name, p.PropertyType); this.Fields.Add(field); } } public string CreateTableScript() { System.Text.StringBuilder script = new StringBuilder(); script.AppendLine("CREATE TABLE " + this.ClassName); script.AppendLine("("); script.AppendLine("/t ID BIGINT,"); for (int i = 0; i < this.Fields.Count; i++) { KeyValuePair<String, Type> field = this.Fields[i]; if (dataMapper.ContainsKey(field.Value)) { script.Append("/t " + field.Key + " " + dataMapper[field.Value]); } else { // Complex Type? script.Append("/t " + field.Key + " BIGINT"); } if (i != this.Fields.Count - 1) { script.Append(","); } script.Append(Environment.NewLine); } script.AppendLine(")"); return script.ToString(); } } }

Puse estas clases en un conjunto para probarlo:

public class FakeDataClass { public int AnInt { get; set; } public string AString { get; set; } public float AFloat { get; set; } public FKClass AFKReference { get; set; } } public class FKClass { public int AFKInt { get; set; } }

Y generó el siguiente SQL:

CREATE TABLE FakeDataClass ( ID BIGINT, AnInt BIGINT, AString NVARCHAR(255), AFloat FLOAT, AFKReference BIGINT ) CREATE TABLE FKClass ( ID BIGINT, AFKInt BIGINT ) GO ALTER TABLE FakeDataClass WITH NOCHECK ADD CONSTRAINT FK_AFKReference FOREIGN KEY (AFKReference) REFERENCES FKClass(ID) GO

Algunos pensamientos adicionales ... Consideraría agregar un atributo como [SqlTable] a sus clases, de esa manera solo genera tablas para las clases que desea. Además, esto se puede limpiar un montón, errores corregidos, optimizados (el FK Checker es una broma), etc., etc. Solo para comenzar.


Para los tipos complejos, puede convertir recursivamente cada uno que encuentre en una tabla propia y luego tratar de gestionar las relaciones de claves externas.

Es posible que también desee especificar previamente qué clases se convertirán o no en tablas. En cuanto a los datos complejos que desea reflejar en la base de datos sin aumentar el esquema, puede tener una o más tablas para tipos diversos. Este ejemplo usa hasta 4:

CREATE TABLE MiscTypes /* may have to include standard types as well */ ( TypeID INT, TypeName VARCHAR(...) ) CREATE TABLE MiscProperties ( PropertyID INT, DeclaringTypeID INT, /* FK to MiscTypes */ PropertyName VARCHAR(...), ValueTypeID INT /* FK to MiscTypes */ ) CREATE TABLE MiscData ( ObjectID INT, TypeID INT ) CREATE TABLE MiscValues ( ObjectID INT, /* FK to MiscData*/ PropertyID INT, Value VARCHAR(...) )


Sé que estás buscando una capa de persistencia completa, pero la tarea hbm2ddl de NHibernate puede hacer esto casi como una línea.

Hay una tarea NAnt disponible para llamarlo que puede ser de su interés.


Subsónico es también otra opción. A menudo lo uso para generar clases de entidades que se asignan a una base de datos. Tiene una utilidad de línea de comandos que le permite especificar tablas, tipos y una serie de otras cosas útiles


Pruebe DaoliteMappingTool para .net. Puede ayudarte a generar las clases. Descargar formulario aquí



Pruebe mi método de extensión CreateSchema para objetos en http://createschema.codeplex.com/

Devuelve una cadena para cualquier objeto que contenga scripts CREATE TABLE.



A partir de 2016 (creo), puede utilizar Entity Framework 6 Code First para generar el esquema SQL de clases poco c # o para usar Database First para generar el código c # de sql. Recorrido de Code First to DB