Autor Tema: Como programar en n-Capas con C# (Parte 1)  (Leído 1442 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Phreaker

Como programar en n-Capas con C# (Parte 1)
« : julio 23, 2010, 05:23:45 pm »
Este es un tema polémico del que se habla mucho y nada, digo que se   habla mucho porque al buscar algo de información en Internet, uno se da   cuenta, que esta plagado de sitios donde preguntan como aplicar   programación en 3 capas, o N-Capas,   pero en muy pocos lugares se responde con algo cierto y concreto, la   mayoría hacen referencia a libros gordos que tardarías en leer semanas   (no estoy en contra de la lectura, es un proceso largo nada más y casi   todos buscamos aprenderlo un poco más rápido). Este artículo también   será bastante largo y me aventuro a decir que me tomará varias noches   escribirlo completamente, pero no será nada comparado con un libro con   un lomo de 15 centímetros :P
La primer gran confusión que noto, es que la mayoría no sabe   diferenciar entre los conceptos
1. Arquitectura de 3 capas: se basa más bien en   como será construido el entorno, una manera de decirlo en romper el   clásico concepto Cliente-Servidor para introducir conceptos como Back   End (Base de Datos), Middleware   (Servidor de Aplicaciones), Front End (Interfaz de Usuario). Este es un   concepto grande que no veremos ahora, pero lo remarco para hacer   entender que no tiene nada que ver con la programación en capas. Se   acerca más a un concepto físico.
2. Programación en 3 (n) capas: este es el tema en   cuestión y estira más hacia un concepto lógico. En cómo partimos,   agrupamos, clasificamos, optimizamos nuestro código. El mismo introduce   conceptos como Capa de Acceso a Datos (Esta nos permite   conectarnos a la fuente de datos y operar contra ella), Capa de    Negocios (es la que se encarga de procesar todo,   validaciones, etc. la misma suele distribuirse en la aplicación en sí y   en la BBDD), y Capa de Presentación (es más   bien lo que el usuario percibe, su interfaz gráfica por lo gral).
Creo que con esos conceptos introductorios ya estamos preparados para   comprender mejor ciertos aspectos de este paradigma.   Para resaltar por último, gracias a la separación en capas quiere decir   que podemos cambiar de proveedor de base de datos, y no necesitaremos   reescribir toda la aplicación de vuelta, sino solamente esa pequeña capa   y reutilizaríamos la interfaz y las reglas de negocios, o también   podemos mantener las reglas de negocios y el motor de base de datos,   y fácilmente cambiarnos de una interfaz WinForm a WebForm,   siempre la más dura de cambiar en la de negocios ya que afecta en un   nivel mínimo a las otras 2 capas.
Creo que ya es suficiente teoría de momento y podemos comenzar con la   acción, el código que voy a ir escribiendo lo haré en Visual Studio   2010 por que es la que tengo instalada ahora mismo en la maquina, pero   funciona desde la versión 2005 con el framework 2.0 en adelante, ya que   ADO.Net no ha sufrido grandes cambios desde esa versión, así que ustedes   lo pueden ir creando en la versión del IDE o framework que más gusten.
Primeramente vamos a crear una solución con un proyecto de   Biblioteca de Clases, el mismo tendrá 3 clases   principales para representar la capa de Acceso a Datos, la primera   llamaremos GDatos.cs, la misma le asignaremos el   namespace AccesoDatos, y una clase abstracta con el   mismo nombre. Haremos uso de estos 2 namespace:
 
1
2
using System;
using System.Data;
    Lo siguiente que haremos será estructurar en código con regiones para   una mayor comodidad en la lectura del mismo, la primer región es la de Declaración   de Variables en la misma creamos las variables o atributos para la   conexion a la BBDD, más un objeto de interfaz de conexión para que sea   implementada de manera específica por la clase hija, si se han dado   cuenta estamos usando ya conceptos de OOP avanzados, y   lo seguiremos usando fuertemente en el transcurso del artículo. Esta es   una clase que obligatoriamente debe ser hereda por otra. El nivel de   acceso por eso están definidas como protected para que sean modificadas   por si misma o por sus clases derivadas.
 
1
2
3
4
5
6
7
8
9
10
#region "Declaración de Variables"
 
protected string MServidor = "";
protected string MBase = "";
protected string MUsuario = "";
protected string MPassword = "";
protected string MCadenaConexion = "";
protected IDbConnection MConexion;
 
#endregion
    Lo siguiente por hacer es muy sencillo, crear los setters y   getters de nuestros atributos anteriormente definidos:
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#region "Setters y Getters"
 
// Nombre del equipo servidor de datos.
public string Servidor
{
   get { return MServidor; }
   set { MServidor = value; }
} // end Servidor
 
// Nombre de la base de datos a utilizar.
public string Base
{
   get { return MBase; }
   set { MBase = value; }
} // end Base
 
// Nombre del Usuario de la BD.
public string Usuario
{
   get { return MUsuario; }
   set { MUsuario = value; }
} // end Usuario
 
// Password del Usuario de la BD.
public string Password
{
   get { return MPassword; }
   set { MPassword = value; }
} // end Password
 
// Cadena de conexión completa a la base.
public abstract string CadenaConexion
{ get; set; }
 
#endregion
 
#region "Privadas"
 
// Crea u obtiene un objeto para conectarse a la base de datos.
protected IDbConnection Conexion
{
   get
   {
      // si aun no tiene asignada la cadena de conexion lo hace
      if (MConexion == null)
         MConexion = CrearConexion(CadenaConexion);
 
      // si no esta abierta aun la conexion, lo abre
      if (MConexion.State != ConnectionState.Open)
         MConexion.Open();
 
      // retorna la conexion en modo interfaz, para que se adapte a cualquier implementacion de los distintos fabricantes de motores de bases de datos
      return MConexion;
   } // end get
} // end Conexion
 
#endregion
    Creamos ahora los métodos para hacer lecturas a la fuente de datos,   lo hacemos ya en esta clase porque son metodos generales que pueden   implementar tal cual las clases hijas. En el caso de los DataReader   que son muy especificos del driver utilizados, vamos a   utilizar el objeto IDataReader que es una interfaz de   implementación general.
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#region "Lecturas"
 
// Obtiene un DataSet a partir de un Procedimiento Almacenado.
public DataSet TraerDataSet(string procedimientoAlmacenado)
{
   var mDataSet = new DataSet();
   CrearDataAdapter(procedimientoAlmacenado).Fill(mDataSet);
   return mDataSet;
} // end TraerDataset
 
//Obtiene un DataSet a partir de un Procedimiento Almacenado y sus parámetros.
public DataSet TraerDataSet(string procedimientoAlmacenado, params Object[] args)
{
   var mDataSet = new DataSet();
   CrearDataAdapter(procedimientoAlmacenado, args).Fill(mDataSet);
   return mDataSet;
} // end TraerDataset
 
// Obtiene un DataSet a partir de un Query Sql.
public DataSet TraerDataSetSql(string comandoSql)
{
   var mDataSet = new DataSet();
   CrearDataAdapterSql(comandoSql).Fill(mDataSet);
   return mDataSet;
} // end TraerDataSetSql
 
// Obtiene un DataTable a partir de un Procedimiento Almacenado.
public DataTable TraerDataTable(string procedimientoAlmacenado)
{ return TraerDataSet(procedimientoAlmacenado).Tables[0].Copy(); } // end TraerDataTable
 
//Obtiene un DataSet a partir de un Procedimiento Almacenado y sus parámetros.
public DataTable TraerDataTable(string procedimientoAlmacenado, params Object[] args)
{ return TraerDataSet(procedimientoAlmacenado, args).Tables[0].Copy(); } // end TraerDataTable
 
//Obtiene un DataTable a partir de un Query SQL
public DataTable TraerDataTableSql(string comandoSql)
{ return TraerDataSetSql(comandoSql).Tables[0].Copy(); } // end TraerDataTableSql
 
// Obtiene un DataReader a partir de un Procedimiento Almacenado.
public IDataReader TraerDataReader(string procedimientoAlmacenado)
{
   var com = Comando(procedimientoAlmacenado);
   return com.ExecuteReader();
} // end TraerDataReader
 
// Obtiene un DataReader a partir de un Procedimiento Almacenado y sus parámetros.
public IDataReader TraerDataReader(string procedimientoAlmacenado, params object[] args)
{
   var com = Comando(procedimientoAlmacenado);
   CargarParametros(com, args);
   return com.ExecuteReader();
} // end TraerDataReader
 
// Obtiene un DataReader a partir de un Procedimiento Almacenado.
public IDataReader TraerDataReaderSql(string comandoSql)
{
   var com = ComandoSql(comandoSql);
   return com.ExecuteReader();
} // end TraerDataReaderSql
 
// Obtiene un Valor Escalar a partir de un Procedimiento Almacenado. Solo funciona con SP's que tengan
// definida variables de tipo output, para funciones escalares mas abajo se declara un metodo
public object TraerValorOutput(string procedimientoAlmacenado)
{
   // asignar el string sql al command
   var com = Comando(procedimientoAlmacenado);
   // ejecutar el command
   com.ExecuteNonQuery();
   // declarar variable de retorno
   Object resp = null;
 
   // recorrer los parametros del SP
   foreach (IDbDataParameter par in com.Parameters)
      // si tiene parametros de tipo IO/Output retornar ese valor
      if (par.Direction == ParameterDirection.InputOutput || par.Direction == ParameterDirection.Output)
         resp = par.Value;
   return resp;
} // end TraerValor
 
// Obtiene un Valor a partir de un Procedimiento Almacenado, y sus parámetros.
public object TraerValorOutput(string procedimientoAlmacenado, params Object[] args)
{
   // asignar el string sql al command
   var com = Comando(procedimientoAlmacenado);
   // cargar los parametros del SP
   CargarParametros(com, args);
   // ejecutar el command
   com.ExecuteNonQuery();
   // declarar variable de retorno
   Object resp = null;
 
   // recorrer los parametros del SP
   foreach (IDbDataParameter par in com.Parameters)
      // si tiene parametros de tipo IO/Output retornar ese valor
      if (par.Direction == ParameterDirection.InputOutput || par.Direction == ParameterDirection.Output)
         resp = par.Value;
   return resp;
} // end TraerValor
 
// Obtiene un Valor Escalar a partir de un Procedimiento Almacenado.
public object TraerValorOutputSql(string comadoSql)
{
   // asignar el string sql al command
   var com = ComandoSql(comadoSql);
   // ejecutar el command
   com.ExecuteNonQuery();
   // declarar variable de retorno
   Object resp = null;
 
   // recorrer los parametros del Query (uso tipico envio de varias sentencias sql en el mismo command)
   foreach (IDbDataParameter par in com.Parameters)
      // si tiene parametros de tipo IO/Output retornar ese valor
      if (par.Direction == ParameterDirection.InputOutput || par.Direction == ParameterDirection.Output)
         resp = par.Value;
   return resp;
} // end TraerValor
 
// Obtiene un Valor de una funcion Escalar a partir de un Procedimiento Almacenado.
public object TraerValorEscalar(string procedimientoAlmacenado)
{
   var com = Comando(procedimientoAlmacenado);
   return com.ExecuteScalar();
} // end TraerValorEscalar
 
/// Obtiene un Valor de una funcion Escalar a partir de un Procedimiento Almacenado, con Params de Entrada
public Object TraerValorEscalar(string procedimientoAlmacenado, params object[] args)
{
   var com = Comando(procedimientoAlmacenado);
   CargarParametros(com, args);
   return com.ExecuteScalar();
} // end TraerValorEscalar
 
// Obtiene un Valor de una funcion Escalar a partir de un Query SQL
public object TraerValorEscalarSql(string comandoSql)
{
   var com = ComandoSql(comandoSql);
   return com.ExecuteScalar();
} // end TraerValorEscalarSql
 
#endregion
    El siguiente bloque es para ejecutar procesos que no devuelven   valores, al inicio tendremos varios métodos abstractos, para que las   clases derivadas estén obligadas a implementarlas a su manera, en un   modo especifico, ya que los objetos connection, command,   dataadapter, son muy específicos y deben ser   implementados por cada una.
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#region "Acciones"
 
protected abstract IDbConnection CrearConexion(string cadena);
protected abstract IDbCommand Comando(string procedimientoAlmacenado);
protected abstract IDbCommand ComandoSql(string comandoSql);
protected abstract IDataAdapter CrearDataAdapter(string procedimientoAlmacenado, params Object[] args);
protected abstract IDataAdapter CrearDataAdapterSql(string comandoSql);
protected abstract void CargarParametros(IDbCommand comando, Object[] args);
 
// metodo sobrecargado para autenticarse contra el motor de BBDD
public bool Autenticar()
{
   if (Conexion.State != ConnectionState.Open)
      Conexion.Open();
   return true;
}// end Autenticar
 
// metodo sobrecargado para autenticarse contra el motor de BBDD
public bool Autenticar(string vUsuario, string vPassword)
{
   MUsuario = vUsuario;
   MPassword = vPassword;
   MConexion = CrearConexion(CadenaConexion);
 
   MConexion.Open();
   return true;
}// end Autenticar
 
 
// cerrar conexion
public void CerrarConexion()
{
   if (Conexion.State != ConnectionState.Closed)
      MConexion.Close();
}
 
// end CerrarConexion
 
 
// Ejecuta un Procedimiento Almacenado en la base.
public int Ejecutar(string procedimientoAlmacenado)
{ return Comando(procedimientoAlmacenado).ExecuteNonQuery(); } // end Ejecutar
 
// Ejecuta un query sql
public int EjecutarSql(string comandoSql)
{ return ComandoSql(comandoSql).ExecuteNonQuery(); } // end Ejecutar
 
//Ejecuta un Procedimiento Almacenado en la base, utilizando los parámetros.
public int Ejecutar(string procedimientoAlmacenado, params  Object[] args)
{
   var com = Comando(procedimientoAlmacenado);
   CargarParametros(com, args);
   var resp = com.ExecuteNonQuery();
   for (var i = 0; i < com.Parameters.Count; i++)
   {
      var par = (IDbDataParameter)com.Parameters[i];
      if (par.Direction == ParameterDirection.InputOutput || par.Direction == ParameterDirection.Output)
         args.SetValue(par.Value, i - 1);
   }// end for
   return resp;
} // end Ejecutar
 
#endregion
    Ahora bien, no podemos olvidarnos de la sección transaccional, no se   utiliza normalmente en todos lados desde la aplicación, pero en procesos   dependientes es necesario, así que si necesitamos usarlo, podemos   crearlo de este modo:
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#region "Transacciones"
 
protected IDbTransaction MTransaccion;
protected bool EnTransaccion;
 
//Comienza una Transacción en la base en uso.
public void IniciarTransaccion()
{
   try
   {
      MTransaccion = Conexion.BeginTransaction();
      EnTransaccion = true;
   }// end try
   finally
   { EnTransaccion = false; }
}// end IniciarTransaccion
 
 
//Confirma la transacción activa.
public void TerminarTransaccion()
{
   try
   { MTransaccion.Commit(); }
   finally
   {
      MTransaccion = null;
      EnTransaccion = false;
   }// end finally
}// end TerminarTransaccion
 
 
//Cancela la transacción activa.
public void AbortarTransaccion()
{
   try
   { MTransaccion.Rollback(); }
   finally
   {
      MTransaccion = null;
      EnTransaccion = false;
   }// end finally
}// end AbortarTransaccion
 
#endregion
    El código completo lo pueden ver aqui:
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
using System;
using System.Data;
 
namespace AccesoDatos
{
    public abstract class GDatos
    {
        #region "Declaración de Variables"
 
        protected string MServidor = "";
        protected string MBase = "";
        protected string MUsuario = "";
        protected string MPassword = "";
        protected string MCadenaConexion = "";
        protected IDbConnection MConexion;
 
        #endregion
 
        #region "Setters y Getters"
 
        // Nombre del equipo servidor de datos.
        public string Servidor
        {
            get { return MServidor; }
            set { MServidor = value; }
        } // end Servidor
 
        // Nombre de la base de datos a utilizar.
        public string Base
        {
            get { return MBase; }
            set { MBase = value; }
        } // end Base
 
        // Nombre del Usuario de la BD.
        public string Usuario
        {
            get { return MUsuario; }
            set { MUsuario = value; }
        } // end Usuario
 
        // Password del Usuario de la BD.
        public string Password
        {
            get { return MPassword; }
            set { MPassword = value; }
        } // end Password
 
        // Cadena de conexión completa a la base.
        public abstract string CadenaConexion
        { get; set; }
 
        #endregion
 
        #region "Privadas"
 
        // Crea u obtiene un objeto para conectarse a la base de datos.
        protected IDbConnection Conexion
        {
            get
            {
                // si aun no tiene asignada la cadena de conexion lo hace
                if (MConexion == null)
                    MConexion = CrearConexion(CadenaConexion);
 
                // si no esta abierta aun la conexion, lo abre
                if (MConexion.State != ConnectionState.Open)
                    MConexion.Open();
 
                // retorna la conexion en modo interfaz, para que se adapte a cualquier implementacion de los distintos fabricantes de motores de bases de datos
                return MConexion;
            } // end get
        } // end Conexion
 
        #endregion
 
        #region "Lecturas"
 
        // Obtiene un DataSet a partir de un Procedimiento Almacenado.
        public DataSet TraerDataSet(string procedimientoAlmacenado)
        {
            var mDataSet = new DataSet();
            CrearDataAdapter(procedimientoAlmacenado).Fill(mDataSet);
            return mDataSet;
        } // end TraerDataset
 
 
        //Obtiene un DataSet a partir de un Procedimiento Almacenado y sus parámetros.
        public DataSet TraerDataSet(string procedimientoAlmacenado, params Object[] args)
        {
            var mDataSet = new DataSet();
            CrearDataAdapter(procedimientoAlmacenado, args).Fill(mDataSet);
            return mDataSet;
        } // end TraerDataset
 
        // Obtiene un DataSet a partir de un Query Sql.
        public DataSet TraerDataSetSql(string comandoSql)
        {
            var mDataSet = new DataSet();
            CrearDataAdapterSql(comandoSql).Fill(mDataSet);
            return mDataSet;
        } // end TraerDataSetSql
 
        // Obtiene un DataTable a partir de un Procedimiento Almacenado.
        public DataTable TraerDataTable(string procedimientoAlmacenado)
        { return TraerDataSet(procedimientoAlmacenado).Tables[0].Copy(); } // end TraerDataTable
 
 
        //Obtiene un DataSet a partir de un Procedimiento Almacenado y sus parámetros.
        public DataTable TraerDataTable(string procedimientoAlmacenado, params Object[] args)
        { return TraerDataSet(procedimientoAlmacenado, args).Tables[0].Copy(); } // end TraerDataTable
 
        //Obtiene un DataTable a partir de un Query SQL
        public DataTable TraerDataTableSql(string comandoSql)
        { return TraerDataSetSql(comandoSql).Tables[0].Copy(); } // end TraerDataTableSql
 
        // Obtiene un DataReader a partir de un Procedimiento Almacenado.
        public IDataReader TraerDataReader(string procedimientoAlmacenado)
        {
            var com = Comando(procedimientoAlmacenado);
            return com.ExecuteReader();
        } // end TraerDataReader
 
 
        // Obtiene un DataReader a partir de un Procedimiento Almacenado y sus parámetros.
        public IDataReader TraerDataReader(string procedimientoAlmacenado, params object[] args)
        {
            var com = Comando(procedimientoAlmacenado);
            CargarParametros(com, args);
            return com.ExecuteReader();
        } // end TraerDataReader
 
        // Obtiene un DataReader a partir de un Procedimiento Almacenado.
        public IDataReader TraerDataReaderSql(string comandoSql)
        {
            var com = ComandoSql(comandoSql);
            return com.ExecuteReader();
        } // end TraerDataReaderSql
 
        // Obtiene un Valor Escalar a partir de un Procedimiento Almacenado. Solo funciona con SP's que tengan
        // definida variables de tipo output, para funciones escalares mas abajo se declara un metodo
        public object TraerValorOutput(string procedimientoAlmacenado)
        {
            // asignar el string sql al command
            var com = Comando(procedimientoAlmacenado);
            // ejecutar el command
            com.ExecuteNonQuery();
            // declarar variable de retorno
            Object resp = null;
 
            // recorrer los parametros del SP
            foreach (IDbDataParameter par in com.Parameters)
                // si tiene parametros de tipo IO/Output retornar ese valor
                if (par.Direction == ParameterDirection.InputOutput || par.Direction == ParameterDirection.Output)
                    resp = par.Value;
            return resp;
        } // end TraerValor
 
 
        // Obtiene un Valor a partir de un Procedimiento Almacenado, y sus parámetros.
        public object TraerValorOutput(string procedimientoAlmacenado, params Object[] args)
        {
            // asignar el string sql al command
            var com = Comando(procedimientoAlmacenado);
            // cargar los parametros del SP
            CargarParametros(com, args);
            // ejecutar el command
            com.ExecuteNonQuery();
            // declarar variable de retorno
            Object resp = null;
 
            // recorrer los parametros del SP
            foreach (IDbDataParameter par in com.Parameters)
                // si tiene parametros de tipo IO/Output retornar ese valor
                if (par.Direction == ParameterDirection.InputOutput || par.Direction == ParameterDirection.Output)
                    resp = par.Value;
            return resp;
        } // end TraerValor
 
        // Obtiene un Valor Escalar a partir de un Procedimiento Almacenado.
        public object TraerValorOutputSql(string comadoSql)
        {
            // asignar el string sql al command
            var com = ComandoSql(comadoSql);
            // ejecutar el command
            com.ExecuteNonQuery();
            // declarar variable de retorno
            Object resp = null;
 
            // recorrer los parametros del Query (uso tipico envio de varias sentencias sql en el mismo command)
            foreach (IDbDataParameter par in com.Parameters)
                // si tiene parametros de tipo IO/Output retornar ese valor
                if (par.Direction == ParameterDirection.InputOutput || par.Direction == ParameterDirection.Output)
                    resp = par.Value;
            return resp;
        } // end TraerValor
 
 
        // Obtiene un Valor de una funcion Escalar a partir de un Procedimiento Almacenado.
        public object TraerValorEscalar(string procedimientoAlmacenado)
        {
            var com = Comando(procedimientoAlmacenado);
            return com.ExecuteScalar();
        } // end TraerValorEscalar
 
        /// Obtiene un Valor de una funcion Escalar a partir de un Procedimiento Almacenado, con Params de Entrada
        public Object TraerValorEscalar(string procedimientoAlmacenado, params object[] args)
        {
            var com = Comando(procedimientoAlmacenado);
            CargarParametros(com, args);
            return com.ExecuteScalar();
        } // end TraerValorEscalar
 
        // Obtiene un Valor de una funcion Escalar a partir de un Query SQL
        public object TraerValorEscalarSql(string comandoSql)
        {
            var com = ComandoSql(comandoSql);
            return com.ExecuteScalar();
        } // end TraerValorEscalarSql
 
        #endregion
 
        #region "Acciones"
 
        protected abstract IDbConnection CrearConexion(string cadena);
        protected abstract IDbCommand Comando(string procedimientoAlmacenado);
        protected abstract IDbCommand ComandoSql(string comandoSql);
        protected abstract IDataAdapter CrearDataAdapter(string procedimientoAlmacenado, params Object[] args);
        protected abstract IDataAdapter CrearDataAdapterSql(string comandoSql);
        protected abstract void CargarParametros(IDbCommand comando, Object[] args);
 
        // metodo sobrecargado para autenticarse contra el motor de BBDD
        public bool Autenticar()
        {
            if (Conexion.State != ConnectionState.Open)
                Conexion.Open();
            return true;
        }// end Autenticar
 
        // metodo sobrecargado para autenticarse contra el motor de BBDD
        public bool Autenticar(string vUsuario, string vPassword)
        {
            MUsuario = vUsuario;
            MPassword = vPassword;
            MConexion = CrearConexion(CadenaConexion);
 
            MConexion.Open();
            return true;
        }// end Autenticar
 
 
        // cerrar conexion
        public void CerrarConexion()
        {
            if (Conexion.State != ConnectionState.Closed)
                MConexion.Close();
        }
 
        // end CerrarConexion
 
 
        // Ejecuta un Procedimiento Almacenado en la base.
        public int Ejecutar(string procedimientoAlmacenado)
        { return Comando(procedimientoAlmacenado).ExecuteNonQuery(); } // end Ejecutar
 
        // Ejecuta un query sql
        public int EjecutarSql(string comandoSql)
        { return ComandoSql(comandoSql).ExecuteNonQuery(); } // end Ejecutar
 
        //Ejecuta un Procedimiento Almacenado en la base, utilizando los parámetros.
        public int Ejecutar(string procedimientoAlmacenado, params  Object[] args)
        {
            var com = Comando(procedimientoAlmacenado);
            CargarParametros(com, args);
            var resp = com.ExecuteNonQuery();
            for (var i = 0; i < com.Parameters.Count; i++)
            {
                var par = (IDbDataParameter)com.Parameters[i];
                if (par.Direction == ParameterDirection.InputOutput || par.Direction == ParameterDirection.Output)
                    args.SetValue(par.Value, i - 1);
            }// end for
            return resp;
        } // end Ejecutar
 
 
        #endregion
 
        #region "Transacciones"
 
        protected IDbTransaction MTransaccion;
        protected bool EnTransaccion;
 
        //Comienza una Transacción en la base en uso.
        public void IniciarTransaccion()
        {
            try
            {
                MTransaccion = Conexion.BeginTransaction();
                EnTransaccion = true;
            }// end try
            finally
            { EnTransaccion = false; }
        }// end IniciarTransaccion
 
 
        //Confirma la transacción activa.
        public void TerminarTransaccion()
        {
            try
            { MTransaccion.Commit()[
AYUDANOS ENVIANDO ESTE TEMA A LAS REDES SOCIALES:
  digg  slashdot  delicious  technorati  facebook  twitter  google  google

SvMembers | Unidos Somos Red!

Como programar en n-Capas con C# (Parte 1)
« : julio 23, 2010, 05:23:45 pm »

Desconectado Negro

Re:Como programar en n-Capas con C# (Parte 1)
« Respuesta #1 : enero 25, 2011, 02:29:29 pm »
Pues esta muy bien la info pero en conclucion no hay teoria sino la explicacion basica en un codigo de conexion a la BD pero esta bien la    info...y en la declaracion de las variables recordar que se tienen que inicialisar....ya que son uno de los pasos mas importantes de la programacion  en C Sharp o C#..

Gracias por la info!!.. :thumb:
Su sistema Operativo es Windows XP  y Utiliza Firefox!

Es de sabios preguntar y de tontos el callar

SvMembers | Unidos Somos Red!

Re:Como programar en n-Capas con C# (Parte 1)
« Respuesta #1 : enero 25, 2011, 02:29:29 pm »

Desconectado grisli

Re:Como programar en n-Capas con C# (Parte 1)
« Respuesta #2 : enero 26, 2011, 12:42:29 pm »
Pues esta muy bien la info pero en conclucion no hay teoria sino la explicacion basica en un codigo de conexion a la BD pero esta bien la    info...y en la declaracion de las variables recordar que se tienen que inicialisar....ya que son uno de los pasos mas importantes de la programacion  en C Sharp o C#..

Gracias por la info!!.. :thumb:

 :dubbio: creo que con los comentarios en cada linea de codigo te da mas que teoria te explica con lujo de detalles que hace esa linea ( //comentario ) y las variables las podes inicializar donde queras siempre y cuando no las este utilizando antes de que las declares  :thumbup:

Desconectado Negro

Re:Como programar en n-Capas con C# (Parte 1)
« Respuesta #3 : enero 26, 2011, 04:29:39 pm »
Sii con se q las // son comentarios pero esta buena la info...en otros lenjuagues se usa #...
o depende pero esta bien...
Su sistema Operativo es Windows XP  y Utiliza Firefox!

Es de sabios preguntar y de tontos el callar

Desconectado Phreaker

Re:Como programar en n-Capas con C# (Parte 1)
« Respuesta #4 : noviembre 14, 2011, 05:31:12 pm »
Sii con se q las // son comentarios pero esta buena la info...en otros lenjuagues se usa #...
o depende pero esta bien...

Bueno y al final lograste hacer lo que querias?

Tags SvM: