2009-02-27 16 views
7

Este es mi primer post en StackOverflow, así que por favor sea amable ...ADO.NET Buenas Prácticas para la conexión y objetos DataAdaptor Ámbito

Tengo algunas preguntas con respecto ámbito de los objetos para ADO.NET.

Cuando conecto a una base de datos, que suelen utilizar código como el siguiente:

OleDbConnection conn = new OleDbConnection("my_connection_string"); 
conn.Open(); 
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * from Employees", conn); 
OleDbCommandBuilder cb = new OleDbCommandBuilder(adapter); 
DataTable dt = new DataTable(); 
adapter.Fill(dt); 
conn.Close(); 
conn.Dispose(); 

Digamos que Ato DataTable resultante a un control de la red y permitir que mis usuarios editar el contenido de la cuadrícula. Ahora, cuando mis usuarios presionan un botón Guardar, necesito llamar a este código:

adapter.Update(dt); 

Aquí están mis preguntas:

1) ¿Es necesario para retener el objeto adaptador que creé cuando originalmente cargada la tabla de datos, o puedo crear otro objeto adaptador en el evento de clic del botón Guardar para realizar la actualización?

2) Si necesito conservar el objeto adaptador original, ¿también necesito mantener el objeto de conexión disponible y abierto?

Entiendo el modelo desconectado de ADO.NET - Estoy confundido en el ámbito del objeto cuando es el momento de actualizar la base de datos. Si alguien pudiera darme algunos consejos sobre las mejores prácticas para este escenario, ¡lo agradecería enormemente!

Gracias de antemano ...

Respuesta

3

1) Usted no necesitan el mismo adaptador de datos, pero si se crea uno nuevo que deben utilizar la misma consulta como su base.

2) El DataAdapter abrirá su conexión si la conexión está cerrada. En ese caso, cerrará la conexión nuevamente una vez que haya finalizado. Si la conexión ya está abierta, dejará la conexión abierta incluso después de que haya finalizado.

Normalmente, trabajaría como en su ejemplo. Cree un Conneciton y un DataAdapter, llene una DataTable y elimine la conexión y el DataAdapter después.

Dos comentarios al código:

  • que no es necesario CommandBuilder aquí ya que sólo hace un selecto. El generador de comandos solo es necesario si desea generar instrucciones Insertar, Actualizar o Eliminar automáticamente. En ese caso, también debe configurar InsertCommand, UpdateCommand o DeleteCommand en el DataAdapter manualmente desde CommandBuilder.
  • Segundo. En lugar de llamar a Dispose manualmente, debe usar la cláusula Using. Asegura que sus objetos serán eliminados incluso si se lanza una excepción.

tratar de cambiar su código para esto:

DataTable dt = new DataTable(); 
using (OleDbConnection conn = new OleDbConnection("my_connection_string")) 
using (OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * from Employees", conn)) 
{ 
    adapter.Fill(dt);  
} 

Tenga en cuenta que defino DataTable fuera de las cláusulas que utilizan. Esto es necesario para asegurarse de que la tabla esté dentro del alcance cuando abandone los usos. También tenga en cuenta que no necesita la llamada Dispose en el DataAdapter o la llamada Close en la conexión. Ambos se hacen de forma implícita cuando dejas los usos.

Oh.Y bienvenidos a SO :-)

+0

Los adaptadores de datos pueden abrir conexiones implícitamente, ahora no estoy seguro de hacer esto dentro de una instrucción using, pero ¿no podría simplemente dejar caer la línea conn.Open() y dejar que el adaptador de datos abra la conexión? – GordonB

+0

Buen punto. Incluso lo mencioné en 2). :-) Actualizaré el código ejemplo –

+0

¿Puede el adaptador de datos ser una buena opción en caso de arrojar millones de registros (por ejemplo: 2-3 millones de registros que tengo en mi datatable) en la base de datos? –

0

Para responder a sus preguntas:

  1. Idealmente, debe conservar el mismo adaptador de datos debido a que ya ha realizado su inicialización. Un DataAdapter proporciona propiedades tales como SelectCommand, UpdateCommand, InsertCommand y DeleteCommand que le permiten establecer diferentes objetos Command para realizar estas diferentes funciones en el origen de datos. Entonces, verá, el DataAdapter es diseñado para ser reutilizado para múltiples comandos (para la misma conexión de base de datos). El uso de CommandBuilder (aunque no recomendado) crea los otros Comandos mediante el análisis de SelectCommand, lo que le permite realizar Actualizaciones, Eliminaciones e Inserciones utilizando el mismo CommandBuilder.

  2. Lo mejor es permitir que el DataAdapter maneje implícitamente las conexiones de la base de datos. @Rune Grimstad ya ha elaborado sobre este comportamiento implícito y es útil para entender esto. Idealmente, las conexiones deberían cerrarse lo antes posible.

0

Hay dos detalles adicionales que vale la pena agregar a la excelente respuesta de Rune Grimstad.

En primer lugar, CommandBuilder (si es necesario) implementa IDisposable, y por lo tanto debe estar envuelto en su propia instrucción 'using'. Sorprendentemente (al menos para mí), Disposing the DataAdapter does not parecen deshacerse del CommandBuilder asociado. El problema que observé cuando fallé en hacer esto fue que, aunque llamé a Dispose en el DataAdapter, y el estado de la conexión fue 'Closed', no pude eliminar una base de datos temporal una vez que utilicé CommandBuilder para actualizar esa base de datos.

En segundo lugar, la instrucción "... En ese caso, también es necesario configurar manualmente InsertCommand, UpdateCommand o DeleteCommand en el DataAdapter ..." no siempre es correcto. Para muchos casos triviales, CommandBuilder creará automáticamente las sentencias INSERT, UPDATE y DELETE correctas basadas en la instrucción SELECT proporcionada al DataAdapter y metadatos de la base de datos. 'Trivial', en este caso, significa que solo se accede a una sola tabla y esa tabla tiene una clave principal que se devuelve como parte de la instrucción SELECT.

Cuestiones relacionadas