post icon

Como programar en n-Capas con C# (Parte 1)

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 😛

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
335
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(); }
            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
 
    }// end class gDatos
}// end namespace

Nota: visto que el post, se está quedando muy largo, lo separaré en partes e iré agrengando de a poco las otras clases y luego las otras capas lógicas.
Parte 2 | Parte 3 | Parte 4 | Parte 5

Comentarios desde Facebook:

Trackbacks/Pingbacks

  1. Молодежка4сезон25серия26серия - 26 noviembre 2016

    Молодежка 4 сезон 25 серия 26 серия

    Молодежка 4 сезон 25 серия 26 серия

  2. molodezhka4sezon212223seriya - 19 noviembre 2016

    Молодежка 4 сезон 21 серия 22 серия 23 серия 24 сери…

    Молодежка 4 сезон 21 серия 22 серия 23 серия 24 сери…

Responder