2010-07-22 18 views
42

Por lo tanto, soy un programador relativamente nuevo que trabaja para obtener un título de licenciatura en ciencias empresariales con una cantidad muy pequeña de experiencia laboral. Al buscar trabajos de pasantía para mi programa, me he dado cuenta de que lo que he escuchado de varios profs - "trabajar con bases de datos representa el 90% de todos los trabajos modernos de informática" - parece que es cierto. Sin embargo, mi programa realmente no tiene cursos con bases de datos hasta el 3er año, así que al menos estoy tratando de aprender algunas cosas por mi cuenta.Mejores prácticas de base de datos para principiantes

He visto muy poco en SO e Internet en general para alguien como yo. Parece que hay toneladas de tutoriales sobre la mecánica de cómo leer y escribir datos en una base de datos, pero poco sobre las mejores prácticas asociadas. Para demostrar lo que estoy hablando, y para ayudar a conseguir a través de mi pregunta real, esto es lo que puede easily be found on the internet:

public static void Main() 
{ 
    using (var conn = new OdbcConnection()) 
    { 
     var command = new OdbcCommand(); 
     command.Connection = conn; 
     command.CommandText = "SELECT * FROM Customer WHERE id = 1"; 
     var dbAdapter = new OdbcDataAdapter(); 
     dbAdapter.SelectCommand = command; 
     var results = new DataTable(); 
     dbAdapter.Fill(results); 
    } 

    // then you would do something like 
    string customerName = (string) results.Rows[0]["name"]; 
} 

Y así sucesivamente. Esto es bastante simple de entender pero obviamente está lleno de problemas. Empecé con un código como este y rápidamente comencé a decir cosas como "bueno, parece tonto tener SQL en todas partes, debería poner todo eso en un archivo de constantes". Y entonces me di cuenta de que era tonto tener esas mismas líneas de código por todo el lugar y sólo hay que poner todas esas cosas con objetos de conexión, etc dentro de un método:

public DataTable GetTableFromDB (string sql) 
{ 
    // code similar to first sample 
}  

string getCustomerSql = String.Format(Constants.SelectAllFromCustomer, customerId); 
DataTable customer = GetTableFromDB(getCustomerSql); 
string customerName = (string) customer.Rows[0]["name"]; 

Esto parecía ser una gran mejora. Ahora es muy fácil, por ejemplo, cambiar de una conexión Odbc a una conexión SQLite. Pero esa última línea, acceder a los datos, todavía parecía incómoda; y todavía es un dolor cambiar un nombre de campo (como pasar de "nombre" a "CustName" o algo así). Empecé a leer sobre using typed Data sets or custom business objects. Todavía estoy un poco confundido por toda la terminología, pero decidí to look into it anyway. Me imagino que es estúpido confiar en un Asistente de base de datos brillante para hacer todo esto por mí (como en los artículos vinculados) antes de que realmente sepa lo que está pasando , y por qué. Así que tomé una puñalada en ella a mí mismo y empecé a recibir cosas como:

public class Customer 
{ 
    public string Name {get; set;} 
    public int Id {get; set;} 

    public void Populate() 
    { 
     string getCustomerSql = String.Format(Constants.SelectAllFromCustomer, this.Id); 
     DataTable customer = GetTableFromDB(getCustomerSql); 
     this.Name = (string) customer.Rows[0]["name"]; 
    } 

    public static IEnumerable<Customer> GetAll() 
    { 
     foreach (...) { 
      // blah blah 
      yield return customer; 
     } 
    } 
} 

para ocultar las cosas mesa feo y proporcionan algunos tipos fuertes, permitiendo que el código fuera simplemente hacer las cosas como

var customer = new Customer(custId); 
customer.Populate(); 
string customerName = customer.Name; 

que es muy agradable. Y si la tabla de clientes cambia, los cambios en el código solo tienen que ocurrir en un solo lugar: dentro de la clase Customer.

Entonces, al final de todo esto, mi pregunta es esta. ¿Mi lenta evolución del código de la base de datos ha ido en la dirección correcta? ¿Y a dónde voy después? Este estilo es muy bueno para bases de datos pequeñas, pero cuando hay toneladas de tablas diferentes, escribir todas esas clases para cada una sería un problema. He escuchado sobre el software que puede generar ese tipo de código para usted, pero todavía estoy confundido por la jerga DAL/ORM/LINQ2SQL/etc y esas enormes piezas de software son abrumadoras. Estoy buscando algunos recursos buenos, no abrumadoramente complejos, que puedan orientarme en la dirección correcta. Todo lo que puedo encontrar sobre este tema son artículos complejos que van más allá de mi cabeza, o artículos que simplemente te muestran cómo usar los asistentes de apuntar y hacer clic en Visual Studio y tal. También tenga en cuenta que estoy buscando información sobre el trabajo con bases de datos en código, no información sobre diseño/normalización de bases de datos ... hay mucho material bueno sobre eso.

Gracias por leer este mural gigante de texto.

+0

Una cosa adicional: ¿debería marcarse como Wiki de la comunidad? Todavía soy bastante nuevo para SO. – jloubert

+7

a) +1 ¡Para una pregunta inteligente y pensando en el futuro! b) No, creo que esta es una pregunta legítima, no una discusión comunitaria (aunque algunos estarían en desacuerdo) c) Probablemente necesites buscar en ORM (Asignación relacional de objetos). Es cómo puede definir programáticamente un enlace entre los objetos en su código y las filas en su base de datos. Deshace todo el componente "SQL en todas partes". – Aren

+1

En mi entorno, tenemos muchas solicitudes de último minuto y nuestra política aquí es "Hacer que funcione", y no hay tiempo en las especificaciones para mucho más. Gran parte de nuestro código es copiar/pegar consultas SQL como la primera. Funciona, y realmente no tiene nada de malo, excepto que tal vez no se ve tan bonito o no sigue ningún patrón de diseño estándar. –

Respuesta

17

¡Muy buena pregunta de hecho y sin duda está en el camino correcto!

Ser ingeniero informático yo mismo, las bases de datos y cómo escribir código para interactuar con bases de datos nunca fue una gran parte de mi título universitario y, por supuesto, soy responsable de todo el código de la base de datos en funcionamiento.

Aquí está mi experiencia, utilizando la tecnología heredada de principios de los 90 en un proyecto y la tecnología moderna con C# y WPF en otro.

Haré todo lo posible para explicar la terminología a medida que avanzo, pero ciertamente todavía no soy un experto.

Tablas, objetos y asignaciones Oh My!

Una base de datos contiene tablas, pero ¿qué es eso realmente? ¡Son solo datos planos relacionados con otros datos planos y si te sumerges y comienzas a agarrar cosas, se va a desorganizar rápidamente! Las cadenas estarán por todas partes, las sentencias SQL repetidas, los registros cargados dos veces, etc. Por lo tanto, generalmente es una buena práctica representar cada registro de tabla (o colección de registros de tablas según sus relaciones) como un único objeto, generalmente referido a como modelo. Esto ayuda a encapsular los datos y proporcionar funcionalidad para mantener y actualizar su estado.

En su publicación su clase de cliente actuaría como el modelo! Entonces ya te has dado cuenta de ese beneficio.

Ahora hay una variedad de herramientas/marcos (LINQ2SQL, dotConnect, Mindscape LightSpeed) que escribirán todo su código de modelo para usted. Al final, están asignando objetos a tablas relacionales o mapeo O/R a medida que se refieren a él.

Como se esperaba cuando su base de datos cambia también lo hacen sus asignaciones de O/R. Al igual que lo que mencionó, si su cliente cambia, debe arreglarlo en un solo lugar, una vez más por qué lo ponemos en clases. En el caso de mi proyecto heredado, los modelos de actualización consumieron mucho tiempo porque eran tantos, mientras que en mi proyecto más reciente son unos pocos clics PERO finalmente el resultado es el mismo.

¿Quién debería saber qué?

En mis dos proyectos ha habido dos formas diferentes de cómo los objetos interactúan con sus tablas.

En algunos campos, los modelos deben saber todo sobre sus tablas, cómo guardarse, tener acceso compartido directo a la conexión/sesión y realizar acciones como Customer.Delete() y Customer.Save() todas ellas solas.

Otros campos, poner lectura, escritura, eliminación, lógica en una clase de gestión. Por ejemplo, MySessionManager.Save(myCustomer). Esta metodología tiene la ventaja de poder implementar fácilmente el seguimiento de cambios en objetos y garantizar que todos los objetos hagan referencia al mismo registro de tabla subyacente. Sin embargo, implementarlo es más complejo que el método mencionado anteriormente de lógica de clase/tabla localizada.

Conclusión

Estás en el camino correcto y en mi opinión interactuar con bases de datos es muy gratificante. Recuerdo mi cabeza girando cuando comencé a investigar yo mismo.

Recomendaría experimentar un poco, iniciar un proyecto pequeño, tal vez un sistema simple de facturación, e intentar escribir los modelos usted mismo. Después de eso, intente con otro pequeño proyecto e intente aprovechar una herramienta de mapeo O/R de la base de datos y vea la diferencia.

+0

Gracias por una respuesta muy bien escrita. Esa fue una buena explicación simple de algunos de los conceptos que estaba buscando. Con respecto a su recomendación, "comience un pequeño proyecto y trate de escribir los modelos usted mismo", bueno, eso es básicamente lo que estoy haciendo en este momento. ¿Tiene alguna recomendación de herramientas de mapeo O/R bien documentadas que le gusten? – jloubert

+0

@jloubert Me alegro de que le haya gustado mi respuesta. Sí, algunas herramientas O/R con las que puedes jugar son 1) Descarga VS Express que viene con SQL Express. Utilizando eso, puede entrar directamente en la acción utilizando Entity Framework (solo admite MS SQL) que le permite arrastrar y soltar tablas para generar sus clases de modelo O 2) Obtenga VS Express y descargue Mindscape LightSpeed ​​Express (GRATIS). También permite que las tablas de arrastrar y soltar generen tus clases de modelo. LightSpeed ​​tiene la ventaja adicional de soportar más que solo MS SQL. Personalmente me gusta LightSpeed. – Matthew

+0

@jloubert Me de nuevo. La ruta de las mejores prácticas probablemente sea la # 1 que mencioné en mi comentario anterior. Algunas de las características de configuración y avanzadas de LightSpeed ​​(es fantástico si usa esas características) pueden dificultar el inicio. Prueba Entity Framework para empezar y estarás funcionando en muy poco tiempo. – Matthew

8

Su evolución está definitivamente en la dirección correcta. Algunas cosas más a considerar:

+0

¡Gracias por los enlaces! – jloubert

2

En mi humilde opinión, definitivamente va por buen camino para trabajar con un código de mantenimiento. Sin embargo, no estoy convencido de que el enfoque se adapte a una aplicación real. Unos pocos pensamientos que pueden ser útiles

  1. Mientras que el código que está escribiendo va a ser muy agradable trabajar con y realmente fácil de mantener, que implica mucho trabajo por adelantado, esto es parte de la razón por la que los magos son muy popular. No son lo mejor para trabajar, pero ahorran mucho tiempo.
  2. Consultar desde la base de datos es solo el comienzo; otra razón para el uso de conjuntos de datos y asistentes mecanografiados en general es que en la mayoría de las aplicaciones, los usuarios en algún momento editarán su información y la enviarán para actualizarla. Los registros individuales están bien, pero ¿qué sucede si sus datos están mejor representados de una manera normalizada con una jerarquía de tablas de 4 de profundidad? Escribir código para generar automáticamente las instrucciones de actualización/inserción/eliminación a mano para que todas las llamadas sean infernales, por lo que las herramientas son la única forma de avanzar. Los DataSets mecanografiados generarán todo el código para realizar estas actualizaciones por usted y tendrán una funcionalidad muy poderosa para manejar actualizaciones/retrocesos desconectados (por ejemplo, del lado del cliente) de modificaciones recientes.
  3. Lo que dijeron los últimos en cuanto a la inyección SQL (que es un gran problema en la industria) y se protegen utilizando un objeto DBCommand y agregando DbParameters.

En general, hay un gran problema al pasar del código a las bases de datos denominado impedance mismatch. Cerrar la brecha es muy complicado y es por eso que la mayoría de la industria depende de herramientas para hacer el trabajo pesado. Mi consejo sería probar a los asistentes, porque al pasar por un asistente no es una prueba de habilidad, aprender todos sus inconvenientes/errores y sus diversas soluciones es una habilidad realmente útil en la industria, y le permitirá llegar a algunos más avanzados. escenarios en la gestión de datos más rápidamente (por ejemplo, la actualización desconectada de una jerarquía de tablas de 4 profundidades que mencioné).

2

Si le tienen un poco de miedo a cosas como Linq to SQL y Entity Framework, puede dar un paso intermedio y explorar algo como iBATIS.NET. Es simplemente una herramienta de mapeo de datos que toma parte del dolor de la administración de la conexión de la base de datos y mapear los conjuntos de resultados a objetos de dominio personalizados.

Todavía tiene que escribir todas sus clases de objetos y SQL, pero mapea todos sus datos en las clases para usted mediante la reflexión, y no tiene que preocuparse por toda la conectividad subyacente (podría fácilmente escribe una herramienta para generar tus clases). Cuando estás en funcionamiento con iBATIS (suponiendo que podría estar interesado), su código empezará a tener este aspecto:

var customer = Helpers.Customers.SelectByCustomerID(1); 

que existe SelectByCustomerID función dentro de la Customers asignador, cuya definición podría ser:

public Customer SelectByCustomerID(int id) 
{ 
    Return Mapper.QueryForObject<Customer>("Customers.SelectByID", id); 
} 

Los "Clientes.SelectByID" mapas en una definición de la declaración XML donde los 'clientes' es el espacio de nombres y 'SelectByID' es el ID del mapa que contiene su SQL:

<statements> 
    <select id="SelectByID" parameterClass="int" resultClass="Customer"> 
     SELECT * FROM Customers WHERE ID = #value# 
    </select> 
</statements> 

o cuando se desea cambiar un cliente puede hacer cosas como:

customer.FirstName = "George" 
customer.LastName = "Costanza" 

Helpers.Customers.Update(customer); 

LINQ a SQL y Entity Framework obtener más elaborado mediante la producción de SQL de forma automática. me gustaría iBATIS porque todavía tengo el control total del SQL y lo que mis objetos de dominio parecen.

Check out iBATIS (ahora migrado a Google und er el nombre MyBatis.NET). Otro gran paquete es NHibernate, que está unos pasos por delante de iBATIS y está más cerca de un ORM completo.

3

Mi consejo si quiere aprender sobre bases de datos, el primer paso es olvidarse del lenguaje de programación, a continuación, olvidarse de qué base de datos está utilizando y aprender SQL. Seguro que hay muchas diferencias entre mySQL, MS SQLserver y Oracle, pero hay tantas cosas iguales.

Más información sobre combinaciones, seleccionar como, formatos de fecha, normalización. Aprenda qué sucede cuando tiene millones y millones de registros y las cosas comienzan a disminuir, luego aprenda a solucionarlo.

Cree un proyecto de prueba relacionado con algo que le interese, por ejemplo, una tienda de bicicletas. Vea lo que sucede cuando agrega algunos millones de productos y algunos millones de clientes y piensa en todas las formas en que los datos deben relacionarse.

Utilice una aplicación de escritorio para ejecutar consultas en una base de datos local (secuela pro, mysql workbench, etc.) ya que es mucho más rápido que cargar el código fuente en un servidor. ¡Y diviértase con ello!

+1

¡Gracias por la respuesta! De hecho, ya he hecho esto un poco. También hice algunas lecturas sobre la normalización y tengo una comprensión decente del SQL básico ... la base de datos a la que quiero conectarme en este proyecto fue diseñada por mí. Varias personas me han dicho que, en el mundo real, a nadie le importa la normalización más allá de la Tercera Forma Normal, excepto en casos muy extremos, por lo que en su mayoría es lo que he buscado hasta ahora. – jloubert

-2

página visual de la base de datos solo con cuadro combinado y la cuadrícula de datos

espacio de nombres

TestDatabase.Model

{ clase de base de datos

{ 
    private MySqlConnection connecting; 
    private MySqlDataAdapter adapter; 

    public Database() 
     { 
     connecting = new MySqlConnection("server=;uid=;pwd=;database=;"); 
     connecting.Open(); 
     } 

    public DataTable GetTable(string tableName) 
    { 
     adapter = new MySqlDataAdapter("SELECT * FROM "+ tableName, connecting); 
     DataSet ds = new DataSet(); 
     adapter.Fill(ds); 

     adapter.UpdateCommand = new MySqlCommandBuilder(adapter).GetUpdateCommand(); 
     adapter.DeleteCommand = new MySqlCommandBuilder(adapter).GetDeleteCommand(); 

     ds.Tables[0].RowChanged += new DataRowChangeEventHandler(Rowchanged); 
     ds.Tables[0].RowDeleted += new DataRowChangeEventHandler(Rowchanged); 

     return ds.Tables[0]; 
    } 
    public void Rowchanged(object sender, DataRowChangeEventArgs args) 
    { 
     adapter.Update(sender as DataTable); 
    } 

} 

}

-2

VMV Databse

namespace TestDatabase.ViewModel 
{ 
    class MainViewModel : INotifyPropertyChanged 
    { 
     private Model.Database database; 

     private DataTable table; 
     public string[] options; 
     public string selected; 

     public DataTable Table 
     { 
      get { return table; } 
      set { table = value; 
        ChangeProperty("Table"); } 
     } 

     public string[] Options 
     { 
      get { return options; } 
     } 

     public string Selected 
     { 
      get { return selected; } 
      set 
      { selected = value; 
       Table = database.GetTable(value); 
      } 
     } 

     public MainViewModel() 
     { 
     database = new Model.Database(); 
      options = new string[] { "" }; // names of tables 

     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     private void ChangeProperty(string name) 
     { 
      if (this.PropertyChanged != null) 
      { 
       this.PropertyChanged(this, new PropertyChangedEventArgs(name)); 
      } 
     } 
    } 
} 
Cuestiones relacionadas