2012-06-27 11 views
7

Estoy trabajando con un objeto DAL que está escrito en un diseño similar al siguiente código. Simplifiqué una gran cantidad del código de código solo para mostrar la configuración.¿Debería reutilizar los objetos SqlConnection, SqlDataAdapter y SqlCommand?

public class UserDatabase : IDisposable 
{ 
    private SqlDataAdapter UserDbAdapter; 
    private SqlCommand UserSelectCommand; 
    private SqlCommand UserInsertCommand; 
    private SqlCommand UserUpdateCommand; 
    private SqlCommand UserDeleteCommand; 

    private System.Data.SqlClient.SqlConnection SQLConnection; 

    public UserDatabase() 
    { 
     this.SQLConnection = new System.Data.SqlClient.SqlConnection(ConnectionString); 
     this.UserDbAdapter= new SqlDataAdapter(); 
     this.UserDbAdapter.DeleteCommand = this.UserDeleteCommand; 
     this.UserDbAdapter.InsertCommand = this.UserInsertCommand; 
     this.UserDbAdapter.SelectCommand = this.UserSelectCommand; 
     this.UserDbAdapter.UpdateCommand = this.UserUpdateCommand; 
    } 

    private bool FillUsers(DataSet UserDataSet, out int numberOfRecords) 
    { 
     bool success = true; 

     numberOfRecords = 0; 
     string errorMsg = null; 

     this.UserDbAdapter.SelectCommand = this.GetUsersSelectCommand(); 

     numberOfRecords = UserDbAdapter.Fill(UserDataSet, UsersTableName); 

     return success; 
    } 

    private SqlCommand GetUserSelectCommand() 
    { 
     if (this.UserSelectCommand==null) 
      this.UserSelectCommand= new System.Data.SqlClient.SqlCommand(); 
     this.UserSelectCommand.CommandText = "dbo.Users_Select"; 
     this.UserSelectCommand.CommandType = System.Data.CommandType.StoredProcedure; 
     this.UserSelectCommand.Connection = this.SQLConnection; 
     this.UserSelectCommand.Parameters.Clear(); 
     this.UserSelectCommand.Parameters.AddRange(new System.Data.SqlClient.SqlParameter[] { 
     new System.Data.SqlClient.SqlParameter("@RETURN_VALUE", System.Data.SqlDbType.Variant, 0, System.Data.ParameterDirection.ReturnValue, false, ((byte)(0)), ((byte)(0)), "", System.Data.DataRowVersion.Current, null)}); 

     return UserSelectCommand; 
    } 

hay múltiples otras funciones de tipo de relleno que se escriben de la misma manera reutilizar el objeto de conexión, SqlCommands y SqlDataAdapter. El SqlDataAdapter gestiona la apertura y el cierre de SqlConnection internamente.

Así que mi pregunta es múltiple. ¿Es este diseño malo? Si es así, ¿por qué?

Si es malo, debe ser cambiado a mantener las cosas en un ámbito más local como la siguiente:

public bool FillUsers(DataSet UserDataSet) 
    { 
     using (SqlConnection conn = new SqlConnection(ConnectionString)) 
     { 
      using (SqlCommand command = GetUsersSelectCommand()) 
      { 
       using (SqlDataAdapter adapter = new SqlDataAdapter(command, conn)) 
       { 
        adapter.Fill(UserDataSet, UsersTableName); 
       } 
      } 
     } 
    } 

Esto tendría que ser hecho para todas las funciones que parece como la creación, eliminación y entonces rehacer sería peor que mantener los artículos alrededor. Sin embargo, esta parece ser la configuración que veo en todas partes en línea.

+0

¿Mide un problema de rendimiento tal que siente la necesidad de optimizar? Las conexiones de la base de datos se agrupan por diseño. No es necesario "rebobinar" en la parte superior. – spender

+0

Una pregunta similar que hice hace unos años: http://stackoverflow.com/questions/226127/multiple-single-instance-of-linq-to-sql-datacontext – spender

+0

No hay problemas de rendimiento vinculados. Estoy comenzando un nuevo proyecto y necesito un objeto de acceso a los datos y tenía curiosidad si esto era "correcto" o si había una mejor manera. – Equixor

Respuesta

8

No, no hay nada de malo en eso. Debe deshacerse de sus objetos que implementan IDisposable tan pronto como haya terminado con ellos.

Dado un SqlConnection, cuando deseche la conexión, la conexión subyacente simplemente se devolverá al grupo. No es necesariamente "cerrado" como podría pensar. Lo mejor es dejar que el grupo de conexiones haga su trabajo. Here es un enlace en la agrupación de conexiones de MSDN a ADO.NET. Tratar de hacer que haga cosas para las que no fue diseñado (algunas personas lo llaman optimizadora, sorprendentemente) suele ser un viaje por el agujero del conejo.

Además, asegúrese de haber medido y observado un problema antes de intentar optimizarlo. (y no me refiero a esto de manera dura, solo a , ahorre tiempo).

+0

El código superior no elimina ninguno de los objetos hasta que se elimine el objeto UserDatabase. Entonces, parece que reutilizarlos iría en contra de esta práctica de diseño. – Equixor

+0

@Equixor: me refería más específicamente a SqlConnection. Su nombre de clase UserDatabase es ligeramente engañoso, porque no es una base de datos real. Quizás podría hacer un método llamado GetUsers(), que devolvería una lista de usuarios. Su segunda publicación de código es la correcta. Mantenerlos cerca es peor (y algunas veces lleva a errores difíciles de reproducir) –

+0

Ok gracias. Estoy seguro de que el diseño general de esto también podría mejorarse. La mayoría de las clases DAL que tenemos son así y completan los conjuntos de datos que luego usa el BLL. – Equixor

Cuestiones relacionadas