reportviewer y rdlc, ejemplo factura (datos...

93
ReportViewer y Rdlc, ejemplo Factura (datos fijos) Hola a todos: El siguiente articulo pretende mostrar la manera de crear un reporte local usando ReportViewer y Local Report o Rdlc enlazando su origen datos (DataSource) a una fuente proveniente de una Lista Genérica de propiedades. Como se que esto puede resultar un tema demasiado complicado cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo sea lo mas descriptivo posible y para ello me apoyare en la mayor cantidad de imágenes posibles, traten de realizar el ejemplo siguiendo el tutorial, si un paso no les queda claro siéntanse con toda confianza de hacer las consultas necesarias, al final del articulo tendrán el link de descarga del proyecto de ejemplo. Los datos los enviaremos desde un formulario simulando ser los datos de una Factura comercial, que contiene Datos del cliente y los artículos adquiridos. Bien, comencemos creando un Formulario y arrastrando los controles necesarios hasta obtener un formulario como este: Agregue un segundo formulario, llámelo FacturaRpt.cs este contendrá el control ReportViewer al cual enlazaremos el LocalReport, asi que agregue uno arrastrándolo desde el cuadro de herramientas.

Upload: lydiep

Post on 21-Sep-2018

312 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

ReportViewer y Rdlc, ejemplo Factura (datos fijos) Hola a todos:

El siguiente articulo pretende mostrar la manera de crear un reporte local usando ReportViewer y

Local Report o Rdlc enlazando su origen datos (DataSource) a una fuente proveniente de una Lista

Genérica de propiedades. Como se que esto puede resultar un tema demasiado complicado

cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo sea lo mas

descriptivo posible y para ello me apoyare en la mayor cantidad de imágenes posibles, traten de

realizar el ejemplo siguiendo el tutorial, si un paso no les queda claro siéntanse con toda confianza

de hacer las consultas necesarias, al final del articulo tendrán el link de descarga del proyecto de

ejemplo.

Los datos los enviaremos desde un formulario simulando ser los datos de una Factura comercial,

que contiene Datos del cliente y los artículos adquiridos.

Bien, comencemos creando un Formulario y arrastrando los controles necesarios hasta obtener un

formulario como este:

Agregue un segundo formulario, llámelo FacturaRpt.cs este contendrá el control ReportViewer al

cual enlazaremos el LocalReport, asi que agregue uno arrastrándolo desde el cuadro de

herramientas.

Page 3: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

compuesta por campos y propiedades.

Inserte una nueva clase y nómbrela EArticulo, la cual contendrá todas las propiedades de la

entidad Articulo, la clase deberá de quedar con esta estructura:

Código C#:

namespace ReportViewerInvoiceReport_CSharp

{

public class EArticulo

{

public int Numero { get; set; }

public string Upc { get; set; }

public string Descripcion { get; set; }

public decimal Piezas { get; set; }

public decimal Precio { get; set; }

public decimal Importe { get; set; }

}

}

Código Vb.Net:

Public Class EArticulo

Public Property Numero() As Integer

Public Property Upc() As String

Public Property Descripcion() As String

Public Property Piezas() As Decimal

Public Property Precio() As Decimal

Public Property Importe() As Decimal

End Class

Después inserte una nueva clase y nómbrela EFactura, esta clase contendrá todas las

propiedades del encabezado de la factura, la clase deberá de quedar con esta estructura:

Código C#:

using System;

using System.Collections.Generic;

namespace ReportViewerInvoiceReport_CSharp

{

public class EFactura

{

public int Numero { get; set; }

public string Nombre { get; set; }

public string Rfc { get; set; }

public string Direccion { get; set; }

public decimal Subtotal { get; set; }

public decimal Iva { get; set; }

public decimal Total { get; set; }

Page 4: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

public DateTime FechaFacturacion { get; set; }

//Creamos una lista con una nueva Instancia de la clase Articulo

//esta lista contendra el detalle de la factura

public List<EArticulo> Detail = new List<EArticulo>();

}

}

Código Vb.Net:

Imports System.Collections.Generic

Public Class EFactura

Public Property Numero() As Integer

Public Property Nombre() As String

Public Property Rfc() As String

Public Property Direccion() As String

Public Property Subtotal() As Decimal

Public Property Iva() As Decimal

Public Property Total() As Decimal

Public Property FechaFacturacion() As DateTime

'Creamos una lista con una nueva Instancia de la clase Articulo

'esta lista contendra el detalle de la factura

Public Detail As New List(Of EArticulo)()

End Class

Configurar el Reporte del informe “Report1.rdlc”

Para poder usar las clases de EFactura para llenar el Encabezado del reporte y EArticulo para el

detalle del mismo, primero debemos de generar el proyecto, para ello localice el menú Generar –

> Generar Solución

Establecer la fuente de datos del Reporte

Active el cuadro Datos del informe, Menú Ver –>Datos del informe

Page 6: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Seleccione la clase EFactura, recuerde que esta clase contiene las propiedades para el

encabezado de la factura y haga Click sobre el botón Finalizar (Si no hubiera generado el proyecto

estas clases no estarían visibles, así que si no las ve por favor cierre la ventana y genere la

solución):

Observe que ya tiene una fuente de datos seleccionada, solo haga Click en el botón Aceptar:

Page 8: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Configurar tamaño y encabezado del informe

Active la regla del informe para ello menú Informe –> Regla

Configure el tamaño del informe, menú Informe –> Propiedades del informe

Un punto muy importante en este paso es tener presente el Ancho o alto del reporte dependiendo

que tipo de orientación se haya elegido, en este caso el ancho es lo que interesa, considere que

Page 9: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

tiene un ancho máximo de 21.59 cm. a este espacio le restara el valor total de los márgenes que

son 2.0 cm en total ya que configuro un margen de 0.5 cm, dando un espacio de trabajo real

disponible de 19.59 cm., si en el diseño de nuestro reporte nos pasamos de este espacio

disponible nuestro reporte en lugar de mostrarnos una hoja nos mostrar ara dos, normalmente la

segunda hoja sin o con pocos datos.

Bien, continuemos…

Agregue un encabezado de reporte, menú Informe –> Agregar encabezado de pagina

Active el cuadro de herramientas, menú Ver –> Cuadro de herramientas:

Arrastre tantos Cuadros de texto como se requieran, recuerde que nuestros datos provienen de

una clase, entonces por cada campo-propiedad de la clase tiene que crear un control Cuadro de

texto para poder visualizar el dato…esto de crear un control por cada propiedades de la clase

origen es únicamente para este reporte, en realidad usted puede elegir que datos mostrar y cuales

no.

Configurar control cuadro de texto:

Click derecho sobre el control cuadro de texto que deseemos configurar:

Recuerde que establecer un nombre a los controles que vayamos utilizando es de vital importancia

porque será en base a este como los identificaremos, en proyectos pequeños tal vez no tenga

problemas si deja los nombres asignados por default pero, en proyectos grandes esta mala

practica nos provocara constantes dolores de cabeza, entonces, nunca olvide ponerle un nombre a

los controles. Considere que el nombre debe de identificar fácilmente al control al que hace

referencia y al dato que contendrá o al cual estará relacionado, en este caso txtFactura es muy

descriptivo, ya que se entiende que es un control textBox o cuadro de texto y que contendrá el

numero de factura.

Para definir el origen del dato que mostrara el control cuadro de texto despliegue el ComboBox

Page 10: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Valor, vera que este estará cargado con las propiedades de las clases las cuales definimos como

fuente de datos, no le será difícil identificar a que clase pertenece cada una ya que al final podra

ver el nombre que le puso al origen de datos.

Desactivar la casilla “Permitir aumentar el alto” puede resultar muy importante para conservar un

buen diseño, tener activada esta casilla permite que el control cambie de tamaño en tiempo de

ejecución adecuándose al tamaño del valor que contiene, modificando con esto el diseño hasta el

punto de generar hojas innecesarias.

Page 12: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

En este ejemplo el campo Factura será del tipo numérico por lo cual para conservar un formato de

numero correcto, tendrá que configurar el lenguaje que utilizara el campo, para mi ubicación

(México) la configuración de lenguaje será “es-Mex”, para configurar esta propiedad:

Seleccione el control cuadro de texto –> Presione F4:

Si no hiciera esto, un formato numérico podría no mostrarse correctamente por ejemplo la cantidad

Mil doscientos cincuenta y seis con cincuenta y seis decimales en México será 1,256.56 pero en

España se escribiría de esta manera 1.256,56. Esta configuración debemos de hacerla aun si en la

Page 13: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

clase Main de nuestro proyecto hayamos definido un lenguaje de manera predeterminada.

Agregar parámetros al Reporte:

Para abarcar mas sobre el tema de ReportViewer y local report, subamos un poco mas el nivel de

nuestro proyecto agregando parámetros al mismo, esto no siempre es necesario así que en este

articulo solo lo haremos para fines ilustrativos, es decir, para cuando lleguemos a necesitarlo

tendremos el conocimiento disponible de como usarlos.

En el Datos del informe –> Click derecho sobre Parametros –> Agregar parametro:

De nuevo, recuerde que nombrar correctamente a cada control que agregamos es de vital

importancia:

Page 15: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Haga lo mismo para el segundo control agregado, veamos como va nuestro diseño del informe:

Para el detalle del informe, agregue un Tabla arrastrándola desde el cuadro de herramientas, vaya

a las propiedades de la tabla recién agregada, ubique la propiedad DataSetName par establecer el

origen de datos y seleccione Detalle, recuerde que ese fue el nombre que establecimos al origen

de datos:

Page 16: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Agregue las columnas que falten para completar el cuerpo del informe, para ello haga Click

derecho sobre la tabla, Insertar columna, Izquierda o derecha.

Después establezca el valor que mostrara cada columna, para ello tiene dos opciones, seleccionar

el valor desde el icono que vera en la esquina superior derecha de cada celda o ir a propiedades

del cuadro de texto tal cual como lo hizo anteriormente:

Establezca el tamaño de fuente, borde, tipo de dato, lenguaje a utilizar (recuerde lo comentado

anteriormente sobre el formato de numero/moneda)

¿Como va nuestro diseño de informe?

Page 17: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Si tienen un resultado como este, pueden dar su tarea por terminada en cuanto al diseño del

informe si aun no lo logran, todo es cuestión que revisen como configurar un control TextBox o

cuadro de texto como gusten llamarlo y ponerse a ver Alineación, tipo de fuente, borde, relleno,

etc…

Hasta aquí daremos por terminado nuestro diseño, ahora vayamos a:

Establecer una Lista Genérica como DataSource de un local report:

Ubique el Formulario contenedor del ReportViewer llamado FacturaRpt, seleccione el icono

superior derecho del reportViewer –> Seleccione el local report que utilizaremos (el único que

hemos diseñado)

Una vez echo lo anterior, genere el evento Load del Formulario, para ello puede hacer doble click

sobre la barra de titulo o seleccionar el form y presionar la tecla de función F4, esto abrirá la caja

de propiedades, en la parte superior podrá ver un icono con forma de “rayo” de color amarillo, haga

Page 18: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

click sobre el para ver los eventos que implementa el control, después ubique el Evento que le

interese implementar en este caso nos interesa el evento “Load”.

Copie y pegue el siguiente código:

Código C#:

using System;

using System.Collections.Generic;

using System.Windows.Forms;

using Microsoft.Reporting.WinForms;

namespace ReportViewerInvoiceReport_CSharp

{

public partial class FacturaRpt : Form

{

//

//Cree dos listas una para el Encabezado y otra para el detalle

//

public List<EFactura> Invoice = new List<EFactura>();

public List<EArticulo> Detail = new List<EArticulo>();

//

//Cree las propiedades publicas Titulo y Empresa

//

public string Titulo { get; set; }

public string Empresa { get; set; }

public FacturaRpt()

{

InitializeComponent();

}

private void FacturaRpt_Load(object sender, EventArgs e)

{

//Limpiemos el DataSource del informe

reportViewer1.LocalReport.DataSources.Clear();

//

//Establezcamos los parámetros que enviaremos al reporte

//recuerde que son dos para el titulo del reporte y para el

nombre de la empresa

//

ReportParameter[] parameters = new ReportParameter[2];

parameters[0] = new ReportParameter("parameterTitulo",

Titulo);

parameters[1] = new ReportParameter("parameterEmpresa",

Empresa);

//

Page 19: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

//Establezcamos la lista como Datasource del informe

//

reportViewer1.LocalReport.DataSources.Add(new

ReportDataSource("Encabezado", Invoice));

reportViewer1.LocalReport.DataSources.Add(new

ReportDataSource("Detalle", Detail));

//

//Enviemos la lista de parametros

//

reportViewer1.LocalReport.SetParameters(parameters);

//

//Hagamos un refresh al reportViewer

//

reportViewer1.RefreshReport();

}

}

}

Código Vb.Net:

Imports Microsoft.Reporting.WinForms

Public Class FacturaRpt

'

'Cree dos listas una para el Encabezado y otra para el detalle

'

Public Invoice As New List(Of EFactura)()

Public Detail As New List(Of EArticulo)()

'

'Cree las propiedades publicas Titulo y Empresa

'

Public Property Titulo() As String

Public Property Empresa() As String

Private Sub FacturaRpt_Load(sender As System.Object, e As

System.EventArgs) Handles MyBase.Load

'Limpiemos el DataSource del informe

ReportViewer1.LocalReport.DataSources.Clear()

'

'Establezcamos los parametros que enviaremos al reporte

'recuerde que son dos para el titulo del reporte y para el nombre

de la empresa

'

Dim parameters As ReportParameter() = New ReportParameter(1) {}

parameters(0) = New ReportParameter("parameterTitulo", Titulo)

parameters(1) = New ReportParameter("parameterEmpresa", Empresa)

Page 20: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

'

'Establezcamos la lista como Datasource del informe

'

ReportViewer1.LocalReport.DataSources.Add(New

ReportDataSource("Encabezado", Invoice))

ReportViewer1.LocalReport.DataSources.Add(New

ReportDataSource("Detalle", Detail))

'

'Enviemos la lista de parametros

'

ReportViewer1.LocalReport.SetParameters(parameters)

'

'Hagamos un refresh al reportViewer

'

ReportViewer1.RefreshReport()

End Sub

End Class

Hagamos lo ultimo que falta, enviar los datos desde el formulario principal:

Genere el Evento load del Formulario principal,

Después de generado el evento trate de seguir estas líneas de código, escriba linea por linea si

copia y pega será mas complicado que comprenda (suponiendo que su experiencia en desarrollo

no es amplia):

Código C#:

Page 21: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

using System;

using System.Collections.Generic;

using System.Linq;

using System.Windows.Forms;

namespace ReportViewerInvoiceReport_CSharp

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

/// <summary>

/// Funcion encargada de llenar el control DataGridView

/// <autor>José Luis García Bautista</autor>

/// </summary>

/// <returns>Una lista generica de la clase artículo</returns>

private static List<EArticulo> FillDgv()

{

//

//Cree una lista generica de la entidad EArticulo

//

List<EArticulo> listaArticulos = new List<EArticulo>();

//

//Instancie la clase EArticulo para agregar datos a la lista

//

EArticulo item = new EArticulo

{

//Establezca valores a cada una de

las propiedades

Numero = 1,

Upc = "7501020405680",

Descripcion = "Descripción del

artículo 1",

Piezas = 6,

Precio = new decimal(12.50),

Importe = (decimal)(6 * 12.5),

};

//

//Agregamos el Item a la lista

//

listaArticulos.Add(item);

EArticulo item1 = new EArticulo

Page 22: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

{

Numero = 2,

Upc = "7501040805610",

Descripcion = "Descripción del

artículo 2",

Piezas = 3,

Precio = new decimal(22.50),

Importe = (decimal)(3 * 22.5),

};

listaArticulos.Add(item1);

EArticulo item2 = new EArticulo

{

Numero = 3,

Upc = "0412200805610",

Descripcion = "Descripción del artículo 3",

Piezas = 20,

Precio = new decimal(52.80),

Importe = (decimal)(20 * 52.80),

};

listaArticulos.Add(item2);

return listaArticulos;

}

private void Form1_Load(object sender, EventArgs e)

{

//

//La funcion GenerateNumber() se utiliza unicamente para

generar un Número

//aleatorio que simulara ser el numerod e factura

txtnumero.Text = GenerateNumber().ToString();

//Establecemos la propiedad AutoGenerateColumns en False para

evitar que se agreguen

//nuevas columnas a la derecha de las que creamos en tiempo

de diseño.

//

dgvdetalle.AutoGenerateColumns = false;

//

//Establecemos el DataSource del control DataGridView

//

dgvdetalle.DataSource = FillDgv();

//

//Mapeamos las propiedades de la clase devuelta por la

Funcion FillDgv()

Page 23: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

//recuerde que esta funcion devuelve una lista del tipo

EArticulo

//

dgvdetalle.Columns["columnNumero"].DataPropertyName =

"Numero";

dgvdetalle.Columns["columnUpc"].DataPropertyName = "Upc";

dgvdetalle.Columns["columnDescripcion"].DataPropertyName =

"Descripcion";

dgvdetalle.Columns["columnPiezas"].DataPropertyName =

"Piezas";

dgvdetalle.Columns["columnPrecio"].DataPropertyName =

"Precio";

dgvdetalle.Columns["columnImporte"].DataPropertyName =

"Importe";

//

//Hacemos las sumatorias usando un método de extensión de

Linq

//

decimal sum = FillDgv().Sum(x => x.Importe);

decimal iva = (Math.Round(((sum / 116) * 16), 2));

decimal subtotal = Math.Round(sum - iva, 2);

txttotal.Text = Convert.ToString(Math.Round(sum, 2));

txtiva.Text = Convert.ToString(iva);

txtsubtotal.Text = Convert.ToString(subtotal);

}

private static int GenerateNumber()

{

Random rdm = new Random();

return rdm.Next();

}

private void InvoiceGenerate()

{

//

//Hacemos una instancia de la clase EFactura para

//llenarla con los valores contenidos en los controles del

Formulario

EFactura invoice = new EFactura();

invoice.Numero = Convert.ToInt32(txtnumero.Text);

invoice.Nombre = txtnombre.Text;

invoice.Rfc = txtrfc.Text;

invoice.Direccion = txtdireccion.Text;

Page 24: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

invoice.FechaFacturacion = dtpfecha.Value.Date;

invoice.Subtotal = Convert.ToDecimal(txtsubtotal.Text);

invoice.Iva = Convert.ToDecimal(txtiva.Text);

invoice.Total = Convert.ToDecimal(txttotal.Text);

//Recorremos los Rows existentes actualmente en el control

DataGridView

//para asignar los datos a las propiedades

foreach (DataGridViewRow row in dgvdetalle.Rows)

{

EArticulo article = new EArticulo();

//

//Vamos tomando los valores de las celdas del row que

estamos

//recorriendo actualmente y asignamos su valor a la

propiedad de la clase intanciada

//

article.Numero =

Convert.ToInt32(row.Cells["columnNumero"].Value);

article.Upc =

Convert.ToString(row.Cells["columnUpc"].Value);

article.Descripcion =

Convert.ToString(row.Cells["columnDescripcion"].Value);

article.Piezas =

Convert.ToDecimal(row.Cells["columnPiezas"].Value);

article.Precio =

Convert.ToDecimal(row.Cells["columnPrecio"].Value);

article.Importe =

Convert.ToDecimal(row.Cells["columnImporte"].Value);

//

//Vamos agregando el Item a la lista del detalle

//

invoice.Detail.Add(article);

}

//

//Creamos una instancia del Formulario que contiene nuestro

//ReportViewer

//

FacturaRpt frm = new FacturaRpt();

//

//Usamos las propiedades publicas del formulario, aqui es

donde enviamos el valor

//que se mostrara en los parametros creados en el

LocalReport, para este ejemplo

Page 25: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

//estamos Seteando los valores directamente pero usted puede

usar algun control

//

frm.Titulo = "Este es un ejemplo de Factura";

frm.Empresa = "Este es un ejemplo del Nombre de la Empresa";

//

//Recuerde que invoice es una Lista Generica declarada en el

FacturaRtp, es una lista

//porque el origen de datos del LocalReport unicamente

permite ser enlazado a objetos que

//implementen IEnumerable.

//

//Usamos el metod Add porque Invoice es una lista e invoice

es una entidad simple

frm.Invoice.Add(invoice);

//

//Enviamos el detalle de la Factura, como Detail es una lista

e invoide.Details tambien

//es un lista del tipo EArticulo bastara con igualarla

//

frm.Detail = invoice.Detail;

frm.Show();

}

private void btnImprimir_Click(object sender, EventArgs e)

{

InvoiceGenerate();

}

}

}

Código Vb.Net:

Public Class Form1

''' <summary>

''' Funcion encargada de llenar el control DataGridView

''' <autor>José Luis García Bautista</autor>

''' </summary>

''' <returns>Una lista generica de la clase artículo</returns>

Private Shared Function FillDgv() As List(Of EArticulo)

'

'Cree una lista generica de la entidad EArticulo

'

Dim listaArticulos As New List(Of EArticulo)()

'

'Instancie la clase EArticulo para agregar datos a la lista

'

'Establezca valores a cada una de las propiedades

Page 26: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Dim item As New EArticulo()

item.Numero = 1

item.Upc = "7501020405680"

item.Descripcion = "Descripción del artículo 1"

item.Piezas = 6

item.Precio = New Decimal(12.5)

item.Importe = CDec(6 * 12.5)

'

'Agregamos el Item a la lista

'

listaArticulos.Add(item)

Dim item1 As New EArticulo()

item1.Numero = 2

item1.Upc = "7501040805610"

item1.Descripcion = "Descripción del artículo 2"

item1.Piezas = 3

item1.Precio = New Decimal(22.5)

item1.Importe = CDec(3 * 22.5)

listaArticulos.Add(item1)

Dim item2 As New EArticulo()

item2.Numero = 3

item2.Upc = "0412200805610"

item2.Descripcion = "Descripción del artículo 3"

item2.Piezas = 20

item2.Precio = New Decimal(52.8)

item2.Importe = CDec(20 * 52.8)

listaArticulos.Add(item2)

Return listaArticulos

End Function

Private Sub Form1_Load(sender As System.Object, e As

System.EventArgs) Handles MyBase.Load

'

'La funcion GenerateNumber() se utiliza unicamente para generar

un Número

'aleatorio que simulara ser el numerod e factura

txtnumero.Text = GenerateNumber().ToString()

'Establecemos la propiedad AutoGenerateColumns en False para

evitar que se agreguen

'nuevas columnas a la derecha de las que creamos en tiempo de

diseño.

Page 27: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

'

dgvdetalle.AutoGenerateColumns = False

'

'Establecemos el DataSource del control DataGridView

'

dgvdetalle.DataSource = FillDgv()

'

'Mapeamos las propiedades de la clase devuelta por la Funcion

FillDgv()

'recuerde que esta funcion devuelve una lista del tipo EArticulo

'

dgvdetalle.Columns("columnNumero").DataPropertyName = "Numero"

dgvdetalle.Columns("columnUpc").DataPropertyName = "Upc"

dgvdetalle.Columns("columnDescripcion").DataPropertyName =

"Descripcion"

dgvdetalle.Columns("columnPiezas").DataPropertyName = "Piezas"

dgvdetalle.Columns("columnPrecio").DataPropertyName = "Precio"

dgvdetalle.Columns("columnImporte").DataPropertyName = "Importe"

'

'Hacemos las sumatorias usando un método de extensión de Linq

'

Dim sum As Decimal = FillDgv().Sum(Function(x) x.Importe)

Dim iva As Decimal = (Math.Round(((sum / 116) * 16), 2))

Dim subtotal As Decimal = Math.Round(sum - iva, 2)

txttotal.Text = Convert.ToString(Math.Round(sum, 2))

txtiva.Text = Convert.ToString(iva)

txtsubtotal.Text = Convert.ToString(subtotal)

End Sub

Private Shared Function GenerateNumber() As Integer

Dim rdm As New Random()

Return rdm.[Next]()

End Function

Private Sub InvoiceGenerate()

'

'Hacemos una instancia de la clase EFactura para

'llenarla con los valores contenidos en los controles del

Formulario

Dim invoice As New EFactura()

invoice.Numero = Convert.ToInt32(txtnumero.Text)

invoice.Nombre = txtnombre.Text

invoice.Rfc = txtrfc.Text

invoice.Direccion = txtdireccion.Text

invoice.FechaFacturacion = dtpfecha.Value.[Date]

Page 28: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

invoice.Subtotal = Convert.ToDecimal(txtsubtotal.Text)

invoice.Iva = Convert.ToDecimal(txtiva.Text)

invoice.Total = Convert.ToDecimal(txttotal.Text)

'Recorremos los Rows existentes actualmente en el control

DataGridView

'para asignar los datos a las propiedades

For Each row As DataGridViewRow In dgvdetalle.Rows

Dim article As New EArticulo()

'

'Vamos tomando los valores de las celdas del row que estamos

'recorriendo actualmente y asignamos su valor a la propiedad

de la clase intanciada

'

article.Numero =

Convert.ToInt32(row.Cells("columnNumero").Value)

article.Upc = Convert.ToString(row.Cells("columnUpc").Value)

article.Descripcion =

Convert.ToString(row.Cells("columnDescripcion").Value)

article.Piezas =

Convert.ToDecimal(row.Cells("columnPiezas").Value)

article.Precio =

Convert.ToDecimal(row.Cells("columnPrecio").Value)

article.Importe =

Convert.ToDecimal(row.Cells("columnImporte").Value)

'

'Vamos agregando el Item a la lista del detalle

'

invoice.Detail.Add(article)

Next

'

'Creamos una instancia del Formulario que contiene nuestro

'ReportViewer

'

Dim frm As New FacturaRpt()

'

'Usamos las propiedades publicas del formulario, aqui es donde

enviamos el valor

'que se mostrara en los parametros creados en el LocalReport,

para este ejemplo

'estamos Seteando los valores directamente pero usted puede usar

algun control

'

frm.Titulo = "Este es un ejemplo de Factura"

frm.Empresa = "Este es un ejemplo del Nombre de la Empresa"

Page 29: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

'

'Recuerde que invoice es una Lista Generica declarada en

FacturaRtp, es una lista

'porque el origen de datos del LocalReport unicamente permite ser

enlazado a objetos que

'implementen IEnumerable.

'

'Usamos el metod Add porque Invoice es una lista e invoice es una

entidad simple

frm.Invoice.Add(invoice)

'

'Enviamos el detalle de la Factura, como Detail es una lista e

invoide.Details tambien

'es un lista del tipo EArticulo bastara con igualarla

'

frm.Detail = invoice.Detail

frm.Show()

End Sub

Private Sub btnImprimir_Click(sender As System.Object, e As

System.EventArgs) Handles btnImprimir.Click

InvoiceGenerate()

End Sub

End Class

Ahora solo queda probar nuestra aplicación:

Llenamos los datos:

Presione el botón Imprimir, si siguió al pie de la letra el Articulo tendrá un reporte como este:

Page 30: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Observe, en el reporte el Formato numérico y Módena, al igual que no tenemos hojas de mas sin

datos…

Ahora, exporte el reporte a Pdf y observe que los márgenes están dentro del limite, sin generar

hojas de mas, ni salirse de los márgenes:

Bueno, hemos llegado al final de este tutorial, en un entrega posterior abordaremos las imágenes

en Reportes Locales y utilizaremos una Bd como fuente de datos para nuestro reporte.

Saludos desde Monterrey, Nuevo León México!

Ejemplo C#

Page 31: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Ejemplo Vb.Net

Nota: El proyecto fue desarrollado en Vs2010 Ultímate usando Framework 4.0

Programación en 3 capas Hola a todos:

Después de tantos meses de tener abandonado el Blog por fin hoy se libera un espacio en mi

agenda, tiempo que he decidido compartir con todos y cada uno de ustedes.

En este articulo hablare y tratare de explicar con los detalles mas mínimos que es la arquitectura 3

capas, cuales son sus ventajas, como empezar un proyecto 3 capas, cuales son las diferencias

entre cada una de ellas, como comunicarlas y como crear un proyecto con la arquitectura 3 capas

utilizando Visual Studio 2012.

Antes de comenzar a leer este articulo recuerde que: “El objetivo no es otro mas que el de orientar

a los Parvulos .Net sobre la arquitectura de software 3 capas, todo lo escrito en este articulo no es

ensayado, no es revisado por nadie mas, por lo cual podría contener errores gramaticales y

sintácticos, el articulo y sus conceptos no pretenden ser la verdad absoluta del tema, siéntase en

confianza de dejar sus comentarios y opiniones en la sección de comentarios al final del mismo y si

lo considera prudente envíeme un correo electrónico por medio del formulario de contacto y por

ultimo si el articulo le es de utilidad por favor considere dejar un comentario de agradecimiento.”

Requisitos: Visual Studio 2012, Framework 4.0, el proveedor de datos SqlCompact 4.0 instalado en

su equipo y muchas ganas de aprender.

Como siempre recomiendo encarecidamente que antes de descargar los proyectos de ejemplo

(que les pondré al final de articulo), traten de hacerlo ustedes mismos siguiendo paso a paso todo

lo que se mencionara aquí, si tienen dudas en uno en especifico no duden en contactarme.

Dicho todo lo anterior, comencemos…

Arquitectura 3 capas en .Net

¿Ha creado usted software?…¿Si?, entonces sabe lo complejo que resulta crear rutinas y

funciones para cada uno de los formularios, importar todas las referencias del motor de base de

datos en cada uno de los formularios, cambiar código aquí y allá (porque tiene copias del mismo

código en muchos lugares), escribir la lógica de validación de campos dentro del evento, corregir

los bugs que pudieran presentarse y no se diga de implementarles mejoras al software, etc., ¿No?

entonces no se preocupe este es un buen manual de como evitarse muchos dolores de cabeza en

diseño de su arquitectura a seguir.

Para que se de una mejor idea de que hablo, por favor descargue este proyecto de ejemplo,

Page 32: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

ejecútelo, analice el código, observe como para realizar una misma funcionalidad en dos lugares

diferentes tuvimos que escribir casi las mismas líneas de código.

A partir de aquí en adelante estaremos trabajando con el proyecto descargado, aplicándole la

Arquitectura 3 capas para demostrar como esta Arquitectura de Diseño nos ayuda a:

Separar responsabilidades, cada capa tiene una función especifica y no interviene con la de las demás.

Reutilizar código

La separación de roles en tres capas, hace mas fácil reemplazar o modificar a una, sin afectar a los módulos restantes

El código de la capa intermedia puede ser reutilizado por múltiples

Capacidad de migrar nuestro motor de Base de Datos sin grandes impactos al resto del proyecto.

Poder cambiar el Front de nuestra aplicación sin afectar a la lógica de nuestra aplicación ni a la Base de datos

Bien como ya hemos mencionado La Arquitectura de diseño 3 capas, consiste en dividir el diseño

del software en sus tres principales componentes:

1. La Interfaz o UI (User interface): Esta Capa es la encargada de interactuar con el

usuario, es decir, son aquellas ventanas, mensajes, cuadros de diálogos o paginas web

(en el caso del desarrollo web), que el usuario final utiliza para comunicarse con la

aplicación, por medio de esta capa el usuario solicita que se ejecuten las tareas

proporcionando parámetros de entrada. Esta capa se comunica con la capa de Lógica de

Negocio, enviando y solicitando información y con la capa de Entidades usando sus

objetos.

2. La lógica de negocio o Business Logic: Se encarga de implementar, como su

nombre lo dice, la lógica del negocio, es decir, todo lo que el Software debe de considerar

antes de realizar una acción o el proceso que debe de seguir después de realizar una

acción. Por ejemplo: Antes de solicitar a la capa de Datos la inserción de un grupo de

registros en una tabla, valida que vayan todos los campos mandatorios dentro de esa

solicitud si esta condición no se cumple entonces rechaza la inserción e informa del

usuario del status de su solicitud, solicitar a la base de datos que valide la presencia de un

registro antes de insertar el siguiente, validar los tipos de datos, etc. esos ejemplos por

mencionar los mas básicos y generales. Esta capa recibe de la Capa de Presentación las

solicitudes, valida que las condiciones que establece el negocio se cumplan antes de

realizar dicha acción o de hacer la respectiva solicitud a la Capa de Acceso a Datos

3. El acceso a Datos o Data Access: Esta capa es la encargada de la comunicación

con la base de datos, en esta capa descansaran todas nuestras acciones CRUD (Create,

Read, Update y Delete), será la única que “sabrá” que motor de base de datos se esta

utilizando pero le será completamente desconocido el “front”, es decir, jamás sabrá si

nuestra aplicación es una aplicación web o desktop. Se encarga de recibir las peticiones de

la Capa de Lógica de Negocio, ejecutar dichas acciones y devolver el resultado a la misma

capa.

4. Capa de Entidades o Entity Layer: Aunque aparentemente es una cuarta capa

realmente no lo es, esta capa se encarga de contener todos aquellos objetos (clases) que

representan al negocio, y esta es la única que puede ser instanciada en las 3 capas

anteriores, es decir, solo ella puede tener comunicación con el resto pero su función se

Page 33: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

limita a únicamente ser un puente de transporte de datos. Esta capa complementa a la

Capa de Negocio

Para una mejor compresión de la comunicación de las 3 capas:

Hasta aquí, hemos visto la teoría de lo que representa la Arquitectura 3 Capas, pero…

¿Como es que debo representar la Arquitectura 3 Capas en un proyecto de Visual Studio?

Para haya es a donde vamos.

1. Abra el Visual Studio 2012 y cree un proyecto Vacío y nómbrelo “CSharp-3Capas-Primer

Entrega”

Page 35: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

4. Seleccione, Instalado –> Visual C# –> Windows –> Aplicación de Windows Forms –> En el

campo Nombre escriba, “Tienda-Presentacion” y presione el botón “Aceptar”.

5. Repita el paso 2, 3 y en el 4°, seleccione un tipo de proyecto “Biblioteca de Clases” y establezca

como nombre “Tienda-LogicaNegocio”

6.Repita el paso 2, 3 y en el 4°, utilice el nombre “Tienda-AccesoDatos”

7. Repita el paso 2, 3 y en el 4° utilice el nombre “Tienda-Entidades”

¿Como va nuestro diseño‟'?

Page 36: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Observe que cuando creamos el proyecto principal en automático se creo un proyecto vacío,

eliminemos ese proyecto para dejar la siguiente estructura:

Ahora ya tenemos nuestra estructura completa, observe que creamos 4 proyectos dentro del

principal (que lo iniciamos como proyecto vacío), recuerde que el proyecto de Entidades en este

caso “Tienda-Entidades” no es una capa, mas bien, complementa a la capa de Lógica de Negocio.

Continuemos con nuestro diseño…

Capa de Entidades

Recuerde que en esta capa estarán alojados los objetos (clases) con los cuales estaremos

trabajando, con estos objetos estaremos persistiendo las tablas de la base de datos que

utilizaremos.

La base de datos que usaremos contiene una sola tabla llamada “Producto” la cual contiene 5

Page 37: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

campos (Id „int’, Descripción „nvarchar’, Marca „nvarchar’, Precio „nvarchar’), por lo cual la Capa de

Entidades contendrá un Objeto llamado Producto con 5 propiedades publicas cada uno de ellos

respetando el tipo de dato con el cual esta declarado en la base de datos.

Para declarar nuestra Entidad Producto:

1. Agregue una clase al proyecto “Tienda-Entidades” y llámela “EProducto” (La letra „E‟ es por

conveción, es decir, todos los objetos de nuestra capa de Entidades llevaran la letra „E‟ al principio

para que desde donde las lleguemos a utilizar sepamos que ese Objeto es una Entidad evitando

con esto confusiones con otros objetos), dentro agregue las siguientes líneas de código:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace Tienda_Entidades

{

public class EProducto

{

public int Id { get; set; }

public string Descripcion { get; set; }

public string Marca { get; set; }

public decimal Precio { get; set; }

}

}

Si tuviéramos mas tablas en nuestra base de datos tendríamos que crear la misma cantidad de

objetos en nuestra capa de Entidades y dentro contendrían la misma cantidad de propiedades

como campos tiene la tabla siempre respetando el tipo de dato con lo que estos campos están

declarados.

Capa de acceso a Datos

Recordemos que la capa de datos es usada por la capa de lógica y la capa de lógica es llamada

por la capa de presentación, así que usaremos ese mismo orden para crear nuestras

configuraciones y nuestras líneas de código.

1. Agreguemos un archivo de configuración (App.Config) a nuestra capa de datos recuerde que

una de las características principales del archivo de configuraciones es que podemos establecer

una cadena de conexión la cual accederemos fácilmente desde cualquier lugar del proyecto que lo

contiene, que es lo que en esta ocasión nos interesa.

Nuestro archivo de configuraciones lo tenemos que agregar en nuestro proyecto de presentación, y

Page 38: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

no porque lo vaya a utilizar sino que nuestro software cada vez que arranque buscara este archivo

en el directorio desde donde se este ejecutando la aplicación, para efectos de prueba será en la

carpeta “..bin\debug” pero cuando nuestro proyecto este instalado, el archivo quedara desplegado

justo en la carpeta raíz de nuestra instalación junto con el “.exe” por tal motivo deberá de estar en

el mismo proyecto que esta marcado como proyecto de inicio.

Para agregar un archivo de configuraciones siga estos pasos:

- Click derecho sobre el proyecto “Tienda-AccesoDatos –> Agregar –> Nuevo elemento

2. En el proyecto que descargaron anteriormente si observaron viene embebida un archivo de base

de datos llamado DataBase1.sdf que noes otra cosa mas que un archivo de base de datos propios

del motor SQlCompact, cree una carpeta en la unidad C y llámela “Proyecto-3Capas”, después

copien este archivo en ese path.

3. Abran el archivo de configuraciones desde el Explorador de soluciones, Copien las siguientes

líneas de código, borren el contenido del App.Config y péguenlas en su lugar:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<configSections>

</configSections>

<connectionStrings>

<add name="cnnString"

connectionString="Data Source=C:\Proyecto-

3Capas\Database1.sdf"

providerName="Microsoft.SqlServerCe.4.0" />

</connectionStrings>

<startup>

<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"

/>

</startup>

Page 39: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

</configuration>

Observen que el DataSource apunta a la carpeta que acabamos de crear en la unidad C “Data

Source=C:\Proyecto-3Capas\Database1.sdf", esta cadena en proyetos reales normalmente

apuntara a un servidor de datos, pero para fines ilustrativos, este directorio nos servirá muy bien.

Volvamos a nuestra Capa de Datos

4. Agreguemos las referencias a las librerías System.Configuration para esto, Click sobre nuestra

capa de datos (proyecto “Tienda-AccesoDatos”) –> Agregar Referencia

5. Agregue una segunda referencia ahora a System.Data.SqlServeCe (esta librería no siempre

aparece, si este es su caso presione el botón Examinar localice la Dll dentro de archivos de

programa y selecciónela), presione Aceptar.

6. Ya tenemos nuestro App.Config(en el proyecto de arranque) apuntando a nuestra base de datos

y tenemos las dos referencias que necesitamos, System.Configuration para poder accesar y leer el

archivo de configuraciones y el System.Data.SqlServerCe para poder usar los objetos de acceso a

Page 40: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

datos propios del motor SQLCOMPACT en nuestra Capa de Datos.

Como nuestra capa de Acceso a Datos, debe de tener la capacidad de Insertar, Leer, Actualizar y

Eliminar registros de la tabla Productos, requiere de una comunicación directa con la capa de

Entidades, para por ejemplo, al momento de que se le solicite la inserción de un Producto en lugar

de enviarle 5 parámetros con los datos del producto se le envié un Objeto y ¿Cual será este

objeto? nada mas y nada menos que nuestro objeto EProductocreado en la capa de Entidades, de

esta manera ya no trabajaremos con datos sino con objetos llenando, enviando y leyendo

propiedades.

Para lograr la comunicación entre la Capa de Datos y la Capa de Entidades se requiere de la

referencia de una en la otra, en este caso la referencia de la Capa de Entidades dentro de la Capa

de Datos, para ello:

7. Click derecho sobre nuestro proyecto “Tienda-AccesoDatos” –> Agregar Referencia

8. Solución –> Proyectos –> Seleccione “Tienda-Entidades”

Page 41: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Observe como se a creado un nuevo elemento en nuestra carpeta de Referencias del proyecto

“Tienda-AccesoDatos”

9. Inserte una clase nueva llamada “ProductoDal” de donde Dal vendrá de Data Access Layer,

dentro de la clase que acaba de crear tiene que declarar el espacio de

nombres System.Configuration, System.Data.SqlServerCe y del proyecto de Entidades, además

tiene que declarar la clase como publica (para que la Capa de Lógica de Negocio pueda tener

acceso a ella)

Ya tenemos el puente de comunicación entre nuestras Entidades y nuestra Capa de Datos. Solo

resta comenzar a codificar las acciones que querramos hacer con nuestra tabla Producto, recuerde

que el objeto ProductoDalúnicamente tiene como responsabilidad trabajar con todo aquello

relacionado con Producto, así que comencemos haciendo la codificación para Insertar, Traer todos

los registros existentes en nuestra tabla Producto, Traer, Actualizar y Eliminar por Id.

Para hacer esta tarea mas sencilla le proporcionare el código que deberá de poner en la clase

“ProductoDal”, pero, trate de escribir el código para vaya analizando la estructura del mismo.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

Page 42: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

//nuestras importaciones del Espacio de nombres que estaremos utilizando,

//recuerde que estas son las referencias que realizamos hace unos

momentos...

using System.Configuration;

using System.Data.SqlServerCe;

using Tienda_Entidades;

namespace Tienda_AccesoDatos

{

//Definimos el acceso de nuestra clase como public, asegurando con

esto su accesibilidad desde

//otros proyectos.

public class ProductoDal

{

//Primero y siguiendo el orden de las acciones CRUD

//Crearemos un Método que se encarga de insertar un nuevo

Producto es nuestra tabla Producto

/// <summary>

/// Inserta un nuevo Producto en la tabla Producto

/// </summary>

/// <param name="producto">Entidad contenedora de los valores a

insertar</param>

/// <autor>José Luis García Bautista</autor>

public void Insert(EProducto producto)

{

//Creamos nuestro objeto de conexion usando nuestro archivo

de configuraciones

using (SqlCeConnection cnx = new

SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToStr

ing()))

{

cnx.Open();

//Declaramos nuestra consulta de Acción Sql parametrizada

const string sqlQuery =

"INSERT INTO Producto (Descripcion, Marca, Precio)

VALUES (@descripcion, @marca, @precio)";

using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery,

cnx))

{

//El primero de los cambios significativos con

respecto al ejemplo descargado es que aqui...

//ya no leeremos controles sino usaremos las

propiedades del Objeto EProducto de nuestra capa

//de entidades...

cmd.Parameters.AddWithValue("@descripcion",

producto.Descripcion);

cmd.Parameters.AddWithValue("@marca",

producto.Marca);

Page 43: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

cmd.Parameters.AddWithValue("@precio",

producto.Precio);

cmd.ExecuteNonQuery();

}

}

}

/// <summary>

/// Devuelve una lista de Productos ordenados por el campo Id de

manera Ascendente

/// </summary>

/// <returns>Lista de productos</returns>

/// <autor>José Luis García Bautista</autor>

public List<EProducto> GetAll()

{

//Declaramos una lista del objeto EProducto la cual será la

encargada de

//regresar una colección de los elementos que se obtengan de

la BD

//

//La lista substituye a DataTable utilizado en el proyecto de

ejemplo

List<EProducto> productos = new List<EProducto>();

using (SqlCeConnection cnx = new

SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToStr

ing()))

{

cnx.Open();

const string sqlQuery = "SELECT * FROM Producto ORDER BY

Id ASC";

using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery,

cnx))

{

SqlCeDataReader dataReader = cmd.ExecuteReader();

//

//Preguntamos si el DataReader fue devuelto con datos

while (dataReader.Read())

{

//

//Instanciamos al objeto Eproducto para llenar

sus propiedades

EProducto producto = new EProducto

{

Page 44: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Id =

Convert.ToInt32(dataReader["Id"]),

Descripcion =

Convert.ToString(dataReader["Descripcion"]),

Marca =

Convert.ToString(dataReader["Marca"]),

Precio =

Convert.ToDecimal(dataReader["Precio"])

};

//

//Insertamos el objeto Producto dentro de la

lista Productos

productos.Add(producto);

}

}

}

return productos;

}

/// <summary>

/// Devuelve un Objeto Producto

/// </summary>

/// <param name="idProducto">Id del producto a buscar</param>

/// <returns>Un registro con los valores del Producto</returns>

/// <autor>José Luis García Bautista</autor>

public EProducto GetByid(int idProducto)

{

using (SqlCeConnection cnx = new

SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToStr

ing()))

{

cnx.Open();

const string sqlGetById = "SELECT * FROM Producto WHERE

Id = @id";

using (SqlCeCommand cmd = new SqlCeCommand(sqlGetById,

cnx))

{

//

//Utilizamos el valor del parámetro idProducto para

enviarlo al parámetro declarado en la consulta

//de selección SQL

cmd.Parameters.AddWithValue("@id", idProducto);

SqlCeDataReader dataReader = cmd.ExecuteReader();

if (dataReader.Read())

{

EProducto producto = new EProducto

Page 45: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

{

Id = Convert.ToInt32(dataReader["Id"]),

Descripcion =

Convert.ToString(dataReader["Descripcion"]),

Marca =

Convert.ToString(dataReader["Marca"]),

Precio =

Convert.ToDecimal(dataReader["Precio"])

};

return producto;

}

}

}

return null;

}

/// <summary>

/// Actualiza el Producto correspondiente al Id proporcionado

/// </summary>

/// <param name="producto">Valores utilizados para hacer el

Update al registro</param>

/// <autor>José Luis García Bautista</autor>

public void Update(EProducto producto)

{

using (SqlCeConnection cnx = new

SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToStr

ing()))

{

cnx.Open();

const string sqlQuery =

"UPDATE Producto SET Descripcion = @descripcion,

Marca = @marca, Precio = @precio WHERE Id = @id";

using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery,

cnx))

{

cmd.Parameters.AddWithValue("@descripcion",

producto.Descripcion);

cmd.Parameters.AddWithValue("@marca",

producto.Marca);

cmd.Parameters.AddWithValue("@precio",

producto.Precio);

cmd.Parameters.AddWithValue("@id", producto.Id);

cmd.ExecuteNonQuery();

}

Page 46: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

}

}

/// <summary>

/// Elimina un registro coincidente con el Id Proporcionado

/// </summary>

/// <param name="idproducto">Id del registro a Eliminar</param>

/// <autor>José Luis García Bautista</autor>

public void Delete(int idproducto)

{

using (SqlCeConnection cnx = new

SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToStr

ing()))

{

cnx.Open();

const string sqlQuery = "DELETE FROM Producto WHERE Id =

@id";

using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery,

cnx))

{

cmd.Parameters.AddWithValue("@id", idproducto);

cmd.ExecuteNonQuery();

}

}

}

}

}

Observe como desde nuestros diferentes Métodos y funciones estamos haciendo uso del

objeto EProductodeclarado en la capa de Entidades…Observe también como nuestra

clase ProductosDal no valida que el valor de las propiedades de EProducto contengan datos o

sean del tipo de dato correcto porque ese ¿es trabajo de?…La Capa de Lógica de Negocio

Capa de Lógica de Negocio

Recuerde que la capa de Lógica es la encargada de establecer toda la lógica que el negocio

establece para llevar a cabo una acción o después de haber realizado un proceso, y esta se

comunica directamente con la Capa de Acceso a Datos, por lo cual tenemos que hacer la

referencia al Proyecto “Tienda-AccesoDatos” y para ello:

1. Click derecho sobre nuestro proyecto “Tienda-LogicaNegocio” –> Agregar Referencia

Page 48: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

9. Agregue una nueva clase y llámela “ProductoBol”, haga los using de las referencias que

acabamos de crear, establezca el nivel de acceso como public y copie la siguiente estructura de

código:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

//

//Hacemos las importaciones del espacio de nombres de los dos proyectos

que referenciamos

//observe como esta capa solo referencio a Tienda-AccessData y no a

Tienda-Presentacion

//observe también como aquí no es requerida la referencia a

System.Data.SqlServerCe

using Tienda_AccesoDatos;

using Tienda_Entidades;

namespace Tienda_LogicaNegocio

{

public class ProductoBol

{

//Instanciamos nuestra clase ProductoDal para poder utilizar sus

miembros

private ProductoDal _productoDal = new ProductoDal();

//

//El uso de la clase StringBuilder nos ayudara a devolver los

mensajes de las validaciones

public readonly StringBuilder stringBuilder = new StringBuilder();

Page 49: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

//

//Creamos nuestro método para Insertar un nuevo Producto, observe

como este método tampoco valida los el contenido

//de las propiedades, sino que manda a llamar a una Función que

tiene como tarea única hacer esta validación

//

public void Registrar(EProducto producto)

{

if(ValidarProducto(producto))

{

if (_productoDal.GetByid(producto.Id) == null)

{

_productoDal.Insert(producto);

}

else

_productoDal.Update(producto);

}

}

public List<EProducto> Todos()

{

return _productoDal.GetAll();

}

public EProducto TraerPorId(int idProduct)

{

stringBuilder.Clear();

if (idProduct == 0) stringBuilder.Append("Por favor

proporcione un valor de Id valido");

if(stringBuilder.Length == 0)

{

return _productoDal.GetByid(idProduct);

}

return null;

}

public void Eliminar(int idProduct)

{

stringBuilder.Clear();

if (idProduct == 0) stringBuilder.Append("Por favor

proporcione un valor de Id valido");

Page 50: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

if (stringBuilder.Length == 0)

{

_productoDal.Delete(idProduct);

}

}

private bool ValidarProducto(EProducto producto)

{

stringBuilder.Clear();

if (string.IsNullOrEmpty(producto.Descripcion))

stringBuilder.Append("El campo Descripción es obligatorio");

if (string.IsNullOrEmpty(producto.Marca))

stringBuilder.Append(Environment.NewLine + "El campo Marca es

obligatorio");

if (producto.Precio <= 0)

stringBuilder.Append(Environment.NewLine + "El campo Precio es

obligatorio");

return stringBuilder.Length == 0;

}

}

}

Analice cada uno de los métodos y funciones que creamos en nuestro primer objeto de nuestra

capa de Negocio, observe:

Cada uno de ellos tiene una sola responsabilidad

La capa de negocio cumple otras tareas y no solo la de ser un puente entre nuestra Capa de Datos y nuestra Capa de Presentación

Como es que estamos usando únicamente objetos y no controles, recuerde que esta capa tampoco sabe que tipo de proyecto es el que la estará usando.

Observe que esta capa no tiene referencias a System.Configuration ni mucho menos aSystem.Data.SqlServerCe.

Observe que en esta capa también se utiliza la Capa de Entidades.

Capa de Presentación o User Interface

Le toca el turno a la Capa de Presentación entrar en escena, esta capa será la encargada de

interactuar con el usuario, la vista de todo nuestro sistema, la encargada de recoger las peticiones

del usuario y de pasar esta misma a la capa de Lógica de Negocio, todo lo que el usuario requiera

se la solicitara a esta y todo lo que Lógica de Negocio devuelva esta se la mostrar al usuario en

forma de datos.

Para configurar nuestra Capa de Presentación.

10. Haga las referencias a los proyecto “Tienda-LogicaNegocio” y “Tienda-Entidades”

Page 51: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

11. En el formulario que tenemos por default llamado “Form1” diseñe una interfaz como la

siguiente:

12. Observe las siguientes líneas de código, genere los eventos involucrados y copie el código de

ejemplo:

using System;

using System.Collections.Generic;

Page 52: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

//

//Hacemos las importaciones del espacio de nombres de los dos proyectos

que referenciamos

//observe como esta capa solo referencio a Tienda-LogicNegocio y a

Tienda-Entidades

//observe como no se referencia a la clase de acceso a Datos

using Tienda_LogicaNegocio;

using Tienda_Entidades;

namespace Tienda_Presentacion

{

public partial class Form1 : Form

{

//

//

//Creamos las instancias de la clase Eproducto y ProductoBol

private EProducto _producto;

private readonly ProductoBol _productoBol = new ProductoBol();

public Form1()

{

InitializeComponent();

}

//

//Creamos los métodos generales llenando y leyendo objetos

//

private void Guardar()

{

try

{

if (_producto == null) _producto = new EProducto();

_producto.Id = Convert.ToInt32(txtId.Text);

_producto.Descripcion = txtDescripcion.Text;

_producto.Marca = txtMarca.Text;

_producto.Precio = Convert.ToDecimal(txtPrecio.Text);

_productoBol.Registrar(_producto);

if (_productoBol.stringBuilder.Length != 0)

Page 53: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

{

MessageBox.Show(_productoBol.stringBuilder.ToString(), "Para

continuar:");

}

else

{

MessageBox.Show("Producto registrado/actualizado con

éxito");

TraerTodos();

}

}

catch (Exception ex)

{

MessageBox.Show(string.Format("Error: {0}", ex.Message),

"Error inesperado");

}

}

private void TraerTodos()

{

List<EProducto> productos = _productoBol.Todos();

if (productos.Count > 0)

{

dgvDatos.AutoGenerateColumns = false;

dgvDatos.DataSource = productos;

dgvDatos.Columns["columnId"].DataPropertyName = "Id";

dgvDatos.Columns["columnDescripcion"].DataPropertyName =

"Descripcion";

dgvDatos.Columns["columnMarca"].DataPropertyName =

"Marca";

dgvDatos.Columns["columnPrecio"].DataPropertyName =

"Precio";

}

else

MessageBox.Show("No existen producto Registrado");

}

private void TraerPorId(int id)

{

try

{

_producto = _productoBol.TraerPorId(id);

if (_producto != null)

Page 54: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

{

txtId.Text = Convert.ToString(_producto.Id);

txtDescripcion.Text = _producto.Descripcion;

txtMarca.Text = _producto.Marca;

txtPrecio.Text = Convert.ToString(_producto.Precio);

}

else

MessageBox.Show("El Producto solicitado no existe");

}

catch (Exception ex)

{

MessageBox.Show(string.Format("Error: {0}", ex.Message),

"Error inesperado");

}

}

private void Eliminar(int id)

{

try

{

_productoBol.Eliminar(id);

MessageBox.Show("Producto eliminado satisfactoriamente");

TraerTodos();

}

catch (Exception ex)

{

MessageBox.Show(string.Format("Error: {0}", ex.Message),

"Error inesperado");

}

}

//

//

//Usamos nuestros metodos y funciones generales, observe como no

hemos repetido codigo en ningun lado

//haciendo con esto que nuestras tareas de actualizacion sean mas

sencillas para nosotros o para

//al asignado en realizarlas...

private void btnAgregar_Click(object sender, EventArgs e)

{

Guardar();

}

private void txtId_KeyDown(object sender, KeyEventArgs e)

{

Page 55: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

if (e.KeyData == Keys.Enter &&

!string.IsNullOrWhiteSpace(txtId.Text))

{

e.SuppressKeyPress = true;

TraerPorId(Convert.ToInt32(txtId.Text));

}

}

private void txtPrecio_KeyDown(object sender, KeyEventArgs e)

{

if (e.KeyData == Keys.Enter)

{

e.SuppressKeyPress = true;

Guardar();

}

}

private void btbnBuscar_Click(object sender, EventArgs e)

{

if (!string.IsNullOrWhiteSpace(txtId.Text))

{

TraerPorId(Convert.ToInt32(txtId.Text));

}

}

private void btnEliminar_Click(object sender, EventArgs e)

{

if (!string.IsNullOrWhiteSpace(txtId.Text))

{

Eliminar(Convert.ToInt32(txtId.Text));

}

}

}

}

De nuevo observe como esta capa desconoce si existe una capa de Datos y mucho menos que

motor de base de datos se utiliza, tampoco se encarga de implementar las reglas de validación ni

de lógica de negocio, su tarea es interactuar con el usuario pidiendo y desplegando información.

¿Que es lo que falta?

Solo nos resta probar el proyecto…pero eso, será tarea suya…Ejecute el proyecto, inserte un

nuevo registro, busque un registro por id, edite su información, elimine un producto, depure el

código línea a línea para viva de paso a paso como es que va pasando de capa de capa enviando

y trayendo información.

Page 56: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Aquí termina nuestro articulo sobre Arquitectura 3 Capas, espero haya sido de su agrado y que la

explicación haya sido lo bastante clara, en caso de que tenga alguna duda por favor deje su

pregunta en la sección de comentarios o escríbame por medio del formulario de contacto.

Escribir este articulo me llevo mas de 4 horas, dejar un comentario de agradecimiento le tomara 5

minutos.

Saludos desde Monterrey, Nuevo León México!

Ejemplo C#

Ejemplo Vb.Net

Programación en 3 capas Hola a todos:

Después de tantos meses de tener abandonado el Blog por fin hoy se libera un espacio en mi

agenda, tiempo que he decidido compartir con todos y cada uno de ustedes.

En este articulo hablare y tratare de explicar con los detalles mas mínimos que es la arquitectura 3

capas, cuales son sus ventajas, como empezar un proyecto 3 capas, cuales son las diferencias

entre cada una de ellas, como comunicarlas y como crear un proyecto con la arquitectura 3 capas

utilizando Visual Studio 2012.

Antes de comenzar a leer este articulo recuerde que: “El objetivo no es otro mas que el de orientar

a los Parvulos .Net sobre la arquitectura de software 3 capas, todo lo escrito en este articulo no es

ensayado, no es revisado por nadie mas, por lo cual podría contener errores gramaticales y

sintácticos, el articulo y sus conceptos no pretenden ser la verdad absoluta del tema, siéntase en

confianza de dejar sus comentarios y opiniones en la sección de comentarios al final del mismo y si

lo considera prudente envíeme un correo electrónico por medio del formulario de contacto y por

ultimo si el articulo le es de utilidad por favor considere dejar un comentario de agradecimiento.”

Requisitos: Visual Studio 2012, Framework 4.0, el proveedor de datos SqlCompact 4.0 instalado en

su equipo y muchas ganas de aprender.

Como siempre recomiendo encarecidamente que antes de descargar los proyectos de ejemplo

(que les pondré al final de articulo), traten de hacerlo ustedes mismos siguiendo paso a paso todo

lo que se mencionara aquí, si tienen dudas en uno en especifico no duden en contactarme.

Dicho todo lo anterior, comencemos…

Arquitectura 3 capas en .Net

¿Ha creado usted software?…¿Si?, entonces sabe lo complejo que resulta crear rutinas y

Page 57: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

funciones para cada uno de los formularios, importar todas las referencias del motor de base de

datos en cada uno de los formularios, cambiar código aquí y allá (porque tiene copias del mismo

código en muchos lugares), escribir la lógica de validación de campos dentro del evento, corregir

los bugs que pudieran presentarse y no se diga de implementarles mejoras al software, etc., ¿No?

entonces no se preocupe este es un buen manual de como evitarse muchos dolores de cabeza en

diseño de su arquitectura a seguir.

Para que se de una mejor idea de que hablo, por favor descargue este proyecto de ejemplo,

ejecútelo, analice el código, observe como para realizar una misma funcionalidad en dos lugares

diferentes tuvimos que escribir casi las mismas líneas de código.

A partir de aquí en adelante estaremos trabajando con el proyecto descargado, aplicándole la

Arquitectura 3 capas para demostrar como esta Arquitectura de Diseño nos ayuda a:

Separar responsabilidades, cada capa tiene una función especifica y no interviene con la de las demás.

Reutilizar código

La separación de roles en tres capas, hace mas fácil reemplazar o modificar a una, sin afectar a los módulos restantes

El código de la capa intermedia puede ser reutilizado por múltiples

Capacidad de migrar nuestro motor de Base de Datos sin grandes impactos al resto del proyecto.

Poder cambiar el Front de nuestra aplicación sin afectar a la lógica de nuestra aplicación ni a la Base de datos

Bien como ya hemos mencionado La Arquitectura de diseño 3 capas, consiste en dividir el diseño

del software en sus tres principales componentes:

1. La Interfaz o UI (User interface): Esta Capa es la encargada de interactuar con el

usuario, es decir, son aquellas ventanas, mensajes, cuadros de diálogos o paginas web

(en el caso del desarrollo web), que el usuario final utiliza para comunicarse con la

aplicación, por medio de esta capa el usuario solicita que se ejecuten las tareas

proporcionando parámetros de entrada. Esta capa se comunica con la capa de Lógica de

Negocio, enviando y solicitando información y con la capa de Entidades usando sus

objetos.

2. La lógica de negocio o Business Logic: Se encarga de implementar, como su

nombre lo dice, la lógica del negocio, es decir, todo lo que el Software debe de considerar

antes de realizar una acción o el proceso que debe de seguir después de realizar una

acción. Por ejemplo: Antes de solicitar a la capa de Datos la inserción de un grupo de

registros en una tabla, valida que vayan todos los campos mandatorios dentro de esa

solicitud si esta condición no se cumple entonces rechaza la inserción e informa del

usuario del status de su solicitud, solicitar a la base de datos que valide la presencia de un

registro antes de insertar el siguiente, validar los tipos de datos, etc. esos ejemplos por

mencionar los mas básicos y generales. Esta capa recibe de la Capa de Presentación las

solicitudes, valida que las condiciones que establece el negocio se cumplan antes de

realizar dicha acción o de hacer la respectiva solicitud a la Capa de Acceso a Datos

3. El acceso a Datos o Data Access: Esta capa es la encargada de la comunicación

con la base de datos, en esta capa descansaran todas nuestras acciones CRUD (Create,

Read, Update y Delete), será la única que “sabrá” que motor de base de datos se esta

utilizando pero le será completamente desconocido el “front”, es decir, jamás sabrá si

Page 58: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

nuestra aplicación es una aplicación web o desktop. Se encarga de recibir las peticiones de

la Capa de Lógica de Negocio, ejecutar dichas acciones y devolver el resultado a la misma

capa.

4. Capa de Entidades o Entity Layer: Aunque aparentemente es una cuarta capa

realmente no lo es, esta capa se encarga de contener todos aquellos objetos (clases) que

representan al negocio, y esta es la única que puede ser instanciada en las 3 capas

anteriores, es decir, solo ella puede tener comunicación con el resto pero su función se

limita a únicamente ser un puente de transporte de datos. Esta capa complementa a la

Capa de Negocio

Para una mejor compresión de la comunicación de las 3 capas:

Hasta aquí, hemos visto la teoría de lo que representa la Arquitectura 3 Capas, pero…

¿Como es que debo representar la Arquitectura 3 Capas en un proyecto de Visual Studio?

Para haya es a donde vamos.

1. Abra el Visual Studio 2012 y cree un proyecto Vacío y nómbrelo “CSharp-3Capas-Primer

Entrega”

Page 60: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

4. Seleccione, Instalado –> Visual C# –> Windows –> Aplicación de Windows Forms –> En el

campo Nombre escriba, “Tienda-Presentacion” y presione el botón “Aceptar”.

5. Repita el paso 2, 3 y en el 4°, seleccione un tipo de proyecto “Biblioteca de Clases” y establezca

como nombre “Tienda-LogicaNegocio”

6.Repita el paso 2, 3 y en el 4°, utilice el nombre “Tienda-AccesoDatos”

7. Repita el paso 2, 3 y en el 4° utilice el nombre “Tienda-Entidades”

¿Como va nuestro diseño‟'?

Page 61: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Observe que cuando creamos el proyecto principal en automático se creo un proyecto vacío,

eliminemos ese proyecto para dejar la siguiente estructura:

Ahora ya tenemos nuestra estructura completa, observe que creamos 4 proyectos dentro del

principal (que lo iniciamos como proyecto vacío), recuerde que el proyecto de Entidades en este

caso “Tienda-Entidades” no es una capa, mas bien, complementa a la capa de Lógica de Negocio.

Continuemos con nuestro diseño…

Capa de Entidades

Recuerde que en esta capa estarán alojados los objetos (clases) con los cuales estaremos

trabajando, con estos objetos estaremos persistiendo las tablas de la base de datos que

utilizaremos.

La base de datos que usaremos contiene una sola tabla llamada “Producto” la cual contiene 5

Page 62: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

campos (Id „int’, Descripción „nvarchar’, Marca „nvarchar’, Precio „nvarchar’), por lo cual la Capa de

Entidades contendrá un Objeto llamado Producto con 5 propiedades publicas cada uno de ellos

respetando el tipo de dato con el cual esta declarado en la base de datos.

Para declarar nuestra Entidad Producto:

1. Agregue una clase al proyecto “Tienda-Entidades” y llámela “EProducto” (La letra „E‟ es por

conveción, es decir, todos los objetos de nuestra capa de Entidades llevaran la letra „E‟ al principio

para que desde donde las lleguemos a utilizar sepamos que ese Objeto es una Entidad evitando

con esto confusiones con otros objetos), dentro agregue las siguientes líneas de código:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace Tienda_Entidades

{

public class EProducto

{

public int Id { get; set; }

public string Descripcion { get; set; }

public string Marca { get; set; }

public decimal Precio { get; set; }

}

}

Si tuviéramos mas tablas en nuestra base de datos tendríamos que crear la misma cantidad de

objetos en nuestra capa de Entidades y dentro contendrían la misma cantidad de propiedades

como campos tiene la tabla siempre respetando el tipo de dato con lo que estos campos están

declarados.

Capa de acceso a Datos

Recordemos que la capa de datos es usada por la capa de lógica y la capa de lógica es llamada

por la capa de presentación, así que usaremos ese mismo orden para crear nuestras

configuraciones y nuestras líneas de código.

1. Agreguemos un archivo de configuración (App.Config) a nuestra capa de datos recuerde que

una de las características principales del archivo de configuraciones es que podemos establecer

una cadena de conexión la cual accederemos fácilmente desde cualquier lugar del proyecto que lo

contiene, que es lo que en esta ocasión nos interesa.

Nuestro archivo de configuraciones lo tenemos que agregar en nuestro proyecto de presentación, y

no porque lo vaya a utilizar sino que nuestro software cada vez que arranque buscara este archivo

en el directorio desde donde se este ejecutando la aplicación, para efectos de prueba será en la

Page 63: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

carpeta “..bin\debug” pero cuando nuestro proyecto este instalado, el archivo quedara desplegado

justo en la carpeta raíz de nuestra instalación junto con el “.exe” por tal motivo deberá de estar en

el mismo proyecto que esta marcado como proyecto de inicio.

Para agregar un archivo de configuraciones siga estos pasos:

- Click derecho sobre el proyecto “Tienda-AccesoDatos –> Agregar –> Nuevo elemento

2. En el proyecto que descargaron anteriormente si observaron viene embebida un archivo de base

de datos llamado DataBase1.sdf que noes otra cosa mas que un archivo de base de datos propios

del motor SQlCompact, cree una carpeta en la unidad C y llámela “Proyecto-3Capas”, después

copien este archivo en ese path.

3. Abran el archivo de configuraciones desde el Explorador de soluciones, Copien las siguientes

líneas de código, borren el contenido del App.Config y péguenlas en su lugar:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<configSections>

</configSections>

<connectionStrings>

<add name="cnnString"

connectionString="Data Source=C:\Proyecto-

3Capas\Database1.sdf"

providerName="Microsoft.SqlServerCe.4.0" />

</connectionStrings>

<startup>

<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"

/>

</startup>

</configuration>

Page 64: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Observen que el DataSource apunta a la carpeta que acabamos de crear en la unidad C “Data

Source=C:\Proyecto-3Capas\Database1.sdf", esta cadena en proyetos reales normalmente

apuntara a un servidor de datos, pero para fines ilustrativos, este directorio nos servirá muy bien.

Volvamos a nuestra Capa de Datos

4. Agreguemos las referencias a las librerías System.Configuration para esto, Click sobre nuestra

capa de datos (proyecto “Tienda-AccesoDatos”) –> Agregar Referencia

5. Agregue una segunda referencia ahora a System.Data.SqlServeCe (esta librería no siempre

aparece, si este es su caso presione el botón Examinar localice la Dll dentro de archivos de

programa y selecciónela), presione Aceptar.

6. Ya tenemos nuestro App.Config(en el proyecto de arranque) apuntando a nuestra base de datos

y tenemos las dos referencias que necesitamos, System.Configuration para poder accesar y leer el

archivo de configuraciones y el System.Data.SqlServerCe para poder usar los objetos de acceso a

datos propios del motor SQLCOMPACT en nuestra Capa de Datos.

Page 65: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Como nuestra capa de Acceso a Datos, debe de tener la capacidad de Insertar, Leer, Actualizar y

Eliminar registros de la tabla Productos, requiere de una comunicación directa con la capa de

Entidades, para por ejemplo, al momento de que se le solicite la inserción de un Producto en lugar

de enviarle 5 parámetros con los datos del producto se le envié un Objeto y ¿Cual será este

objeto? nada mas y nada menos que nuestro objeto EProductocreado en la capa de Entidades, de

esta manera ya no trabajaremos con datos sino con objetos llenando, enviando y leyendo

propiedades.

Para lograr la comunicación entre la Capa de Datos y la Capa de Entidades se requiere de la

referencia de una en la otra, en este caso la referencia de la Capa de Entidades dentro de la Capa

de Datos, para ello:

7. Click derecho sobre nuestro proyecto “Tienda-AccesoDatos” –> Agregar Referencia

8. Solución –> Proyectos –> Seleccione “Tienda-Entidades”

Observe como se a creado un nuevo elemento en nuestra carpeta de Referencias del proyecto

Page 66: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

“Tienda-AccesoDatos”

9. Inserte una clase nueva llamada “ProductoDal” de donde Dal vendrá de Data Access Layer,

dentro de la clase que acaba de crear tiene que declarar el espacio de

nombres System.Configuration, System.Data.SqlServerCe y del proyecto de Entidades, además

tiene que declarar la clase como publica (para que la Capa de Lógica de Negocio pueda tener

acceso a ella)

Ya tenemos el puente de comunicación entre nuestras Entidades y nuestra Capa de Datos. Solo

resta comenzar a codificar las acciones que querramos hacer con nuestra tabla Producto, recuerde

que el objeto ProductoDalúnicamente tiene como responsabilidad trabajar con todo aquello

relacionado con Producto, así que comencemos haciendo la codificación para Insertar, Traer todos

los registros existentes en nuestra tabla Producto, Traer, Actualizar y Eliminar por Id.

Para hacer esta tarea mas sencilla le proporcionare el código que deberá de poner en la clase

“ProductoDal”, pero, trate de escribir el código para vaya analizando la estructura del mismo.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

//nuestras importaciones del Espacio de nombres que estaremos utilizando,

Page 67: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

//recuerde que estas son las referencias que realizamos hace unos

momentos...

using System.Configuration;

using System.Data.SqlServerCe;

using Tienda_Entidades;

namespace Tienda_AccesoDatos

{

//Definimos el acceso de nuestra clase como public, asegurando con

esto su accesibilidad desde

//otros proyectos.

public class ProductoDal

{

//Primero y siguiendo el orden de las acciones CRUD

//Crearemos un Método que se encarga de insertar un nuevo

Producto es nuestra tabla Producto

/// <summary>

/// Inserta un nuevo Producto en la tabla Producto

/// </summary>

/// <param name="producto">Entidad contenedora de los valores a

insertar</param>

/// <autor>José Luis García Bautista</autor>

public void Insert(EProducto producto)

{

//Creamos nuestro objeto de conexion usando nuestro archivo

de configuraciones

using (SqlCeConnection cnx = new

SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToStr

ing()))

{

cnx.Open();

//Declaramos nuestra consulta de Acción Sql parametrizada

const string sqlQuery =

"INSERT INTO Producto (Descripcion, Marca, Precio)

VALUES (@descripcion, @marca, @precio)";

using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery,

cnx))

{

//El primero de los cambios significativos con

respecto al ejemplo descargado es que aqui...

//ya no leeremos controles sino usaremos las

propiedades del Objeto EProducto de nuestra capa

//de entidades...

cmd.Parameters.AddWithValue("@descripcion",

producto.Descripcion);

cmd.Parameters.AddWithValue("@marca",

producto.Marca);

Page 68: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

cmd.Parameters.AddWithValue("@precio",

producto.Precio);

cmd.ExecuteNonQuery();

}

}

}

/// <summary>

/// Devuelve una lista de Productos ordenados por el campo Id de

manera Ascendente

/// </summary>

/// <returns>Lista de productos</returns>

/// <autor>José Luis García Bautista</autor>

public List<EProducto> GetAll()

{

//Declaramos una lista del objeto EProducto la cual será la

encargada de

//regresar una colección de los elementos que se obtengan de

la BD

//

//La lista substituye a DataTable utilizado en el proyecto de

ejemplo

List<EProducto> productos = new List<EProducto>();

using (SqlCeConnection cnx = new

SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToStr

ing()))

{

cnx.Open();

const string sqlQuery = "SELECT * FROM Producto ORDER BY

Id ASC";

using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery,

cnx))

{

SqlCeDataReader dataReader = cmd.ExecuteReader();

//

//Preguntamos si el DataReader fue devuelto con datos

while (dataReader.Read())

{

//

//Instanciamos al objeto Eproducto para llenar

sus propiedades

EProducto producto = new EProducto

{

Page 69: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Id =

Convert.ToInt32(dataReader["Id"]),

Descripcion =

Convert.ToString(dataReader["Descripcion"]),

Marca =

Convert.ToString(dataReader["Marca"]),

Precio =

Convert.ToDecimal(dataReader["Precio"])

};

//

//Insertamos el objeto Producto dentro de la

lista Productos

productos.Add(producto);

}

}

}

return productos;

}

/// <summary>

/// Devuelve un Objeto Producto

/// </summary>

/// <param name="idProducto">Id del producto a buscar</param>

/// <returns>Un registro con los valores del Producto</returns>

/// <autor>José Luis García Bautista</autor>

public EProducto GetByid(int idProducto)

{

using (SqlCeConnection cnx = new

SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToStr

ing()))

{

cnx.Open();

const string sqlGetById = "SELECT * FROM Producto WHERE

Id = @id";

using (SqlCeCommand cmd = new SqlCeCommand(sqlGetById,

cnx))

{

//

//Utilizamos el valor del parámetro idProducto para

enviarlo al parámetro declarado en la consulta

//de selección SQL

cmd.Parameters.AddWithValue("@id", idProducto);

SqlCeDataReader dataReader = cmd.ExecuteReader();

if (dataReader.Read())

{

EProducto producto = new EProducto

Page 70: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

{

Id = Convert.ToInt32(dataReader["Id"]),

Descripcion =

Convert.ToString(dataReader["Descripcion"]),

Marca =

Convert.ToString(dataReader["Marca"]),

Precio =

Convert.ToDecimal(dataReader["Precio"])

};

return producto;

}

}

}

return null;

}

/// <summary>

/// Actualiza el Producto correspondiente al Id proporcionado

/// </summary>

/// <param name="producto">Valores utilizados para hacer el

Update al registro</param>

/// <autor>José Luis García Bautista</autor>

public void Update(EProducto producto)

{

using (SqlCeConnection cnx = new

SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToStr

ing()))

{

cnx.Open();

const string sqlQuery =

"UPDATE Producto SET Descripcion = @descripcion,

Marca = @marca, Precio = @precio WHERE Id = @id";

using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery,

cnx))

{

cmd.Parameters.AddWithValue("@descripcion",

producto.Descripcion);

cmd.Parameters.AddWithValue("@marca",

producto.Marca);

cmd.Parameters.AddWithValue("@precio",

producto.Precio);

cmd.Parameters.AddWithValue("@id", producto.Id);

cmd.ExecuteNonQuery();

}

Page 71: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

}

}

/// <summary>

/// Elimina un registro coincidente con el Id Proporcionado

/// </summary>

/// <param name="idproducto">Id del registro a Eliminar</param>

/// <autor>José Luis García Bautista</autor>

public void Delete(int idproducto)

{

using (SqlCeConnection cnx = new

SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToStr

ing()))

{

cnx.Open();

const string sqlQuery = "DELETE FROM Producto WHERE Id =

@id";

using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery,

cnx))

{

cmd.Parameters.AddWithValue("@id", idproducto);

cmd.ExecuteNonQuery();

}

}

}

}

}

Observe como desde nuestros diferentes Métodos y funciones estamos haciendo uso del

objeto EProductodeclarado en la capa de Entidades…Observe también como nuestra

clase ProductosDal no valida que el valor de las propiedades de EProducto contengan datos o

sean del tipo de dato correcto porque ese ¿es trabajo de?…La Capa de Lógica de Negocio

Capa de Lógica de Negocio

Recuerde que la capa de Lógica es la encargada de establecer toda la lógica que el negocio

establece para llevar a cabo una acción o después de haber realizado un proceso, y esta se

comunica directamente con la Capa de Acceso a Datos, por lo cual tenemos que hacer la

referencia al Proyecto “Tienda-AccesoDatos” y para ello:

1. Click derecho sobre nuestro proyecto “Tienda-LogicaNegocio” –> Agregar Referencia

Page 73: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

9. Agregue una nueva clase y llámela “ProductoBol”, haga los using de las referencias que

acabamos de crear, establezca el nivel de acceso como public y copie la siguiente estructura de

código:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

//

//Hacemos las importaciones del espacio de nombres de los dos proyectos

que referenciamos

//observe como esta capa solo referencio a Tienda-AccessData y no a

Tienda-Presentacion

//observe también como aquí no es requerida la referencia a

System.Data.SqlServerCe

using Tienda_AccesoDatos;

using Tienda_Entidades;

namespace Tienda_LogicaNegocio

{

public class ProductoBol

{

//Instanciamos nuestra clase ProductoDal para poder utilizar sus

miembros

private ProductoDal _productoDal = new ProductoDal();

//

//El uso de la clase StringBuilder nos ayudara a devolver los

mensajes de las validaciones

public readonly StringBuilder stringBuilder = new StringBuilder();

Page 74: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

//

//Creamos nuestro método para Insertar un nuevo Producto, observe

como este método tampoco valida los el contenido

//de las propiedades, sino que manda a llamar a una Función que

tiene como tarea única hacer esta validación

//

public void Registrar(EProducto producto)

{

if(ValidarProducto(producto))

{

if (_productoDal.GetByid(producto.Id) == null)

{

_productoDal.Insert(producto);

}

else

_productoDal.Update(producto);

}

}

public List<EProducto> Todos()

{

return _productoDal.GetAll();

}

public EProducto TraerPorId(int idProduct)

{

stringBuilder.Clear();

if (idProduct == 0) stringBuilder.Append("Por favor

proporcione un valor de Id valido");

if(stringBuilder.Length == 0)

{

return _productoDal.GetByid(idProduct);

}

return null;

}

public void Eliminar(int idProduct)

{

stringBuilder.Clear();

if (idProduct == 0) stringBuilder.Append("Por favor

proporcione un valor de Id valido");

Page 75: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

if (stringBuilder.Length == 0)

{

_productoDal.Delete(idProduct);

}

}

private bool ValidarProducto(EProducto producto)

{

stringBuilder.Clear();

if (string.IsNullOrEmpty(producto.Descripcion))

stringBuilder.Append("El campo Descripción es obligatorio");

if (string.IsNullOrEmpty(producto.Marca))

stringBuilder.Append(Environment.NewLine + "El campo Marca es

obligatorio");

if (producto.Precio <= 0)

stringBuilder.Append(Environment.NewLine + "El campo Precio es

obligatorio");

return stringBuilder.Length == 0;

}

}

}

Analice cada uno de los métodos y funciones que creamos en nuestro primer objeto de nuestra

capa de Negocio, observe:

Cada uno de ellos tiene una sola responsabilidad

La capa de negocio cumple otras tareas y no solo la de ser un puente entre nuestra Capa de Datos y nuestra Capa de Presentación

Como es que estamos usando únicamente objetos y no controles, recuerde que esta capa tampoco sabe que tipo de proyecto es el que la estará usando.

Observe que esta capa no tiene referencias a System.Configuration ni mucho menos aSystem.Data.SqlServerCe.

Observe que en esta capa también se utiliza la Capa de Entidades.

Capa de Presentación o User Interface

Le toca el turno a la Capa de Presentación entrar en escena, esta capa será la encargada de

interactuar con el usuario, la vista de todo nuestro sistema, la encargada de recoger las peticiones

del usuario y de pasar esta misma a la capa de Lógica de Negocio, todo lo que el usuario requiera

se la solicitara a esta y todo lo que Lógica de Negocio devuelva esta se la mostrar al usuario en

forma de datos.

Para configurar nuestra Capa de Presentación.

10. Haga las referencias a los proyecto “Tienda-LogicaNegocio” y “Tienda-Entidades”

Page 76: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

11. En el formulario que tenemos por default llamado “Form1” diseñe una interfaz como la

siguiente:

12. Observe las siguientes líneas de código, genere los eventos involucrados y copie el código de

ejemplo:

using System;

using System.Collections.Generic;

Page 77: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

//

//Hacemos las importaciones del espacio de nombres de los dos proyectos

que referenciamos

//observe como esta capa solo referencio a Tienda-LogicNegocio y a

Tienda-Entidades

//observe como no se referencia a la clase de acceso a Datos

using Tienda_LogicaNegocio;

using Tienda_Entidades;

namespace Tienda_Presentacion

{

public partial class Form1 : Form

{

//

//

//Creamos las instancias de la clase Eproducto y ProductoBol

private EProducto _producto;

private readonly ProductoBol _productoBol = new ProductoBol();

public Form1()

{

InitializeComponent();

}

//

//Creamos los métodos generales llenando y leyendo objetos

//

private void Guardar()

{

try

{

if (_producto == null) _producto = new EProducto();

_producto.Id = Convert.ToInt32(txtId.Text);

_producto.Descripcion = txtDescripcion.Text;

_producto.Marca = txtMarca.Text;

_producto.Precio = Convert.ToDecimal(txtPrecio.Text);

_productoBol.Registrar(_producto);

if (_productoBol.stringBuilder.Length != 0)

Page 78: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

{

MessageBox.Show(_productoBol.stringBuilder.ToString(), "Para

continuar:");

}

else

{

MessageBox.Show("Producto registrado/actualizado con

éxito");

TraerTodos();

}

}

catch (Exception ex)

{

MessageBox.Show(string.Format("Error: {0}", ex.Message),

"Error inesperado");

}

}

private void TraerTodos()

{

List<EProducto> productos = _productoBol.Todos();

if (productos.Count > 0)

{

dgvDatos.AutoGenerateColumns = false;

dgvDatos.DataSource = productos;

dgvDatos.Columns["columnId"].DataPropertyName = "Id";

dgvDatos.Columns["columnDescripcion"].DataPropertyName =

"Descripcion";

dgvDatos.Columns["columnMarca"].DataPropertyName =

"Marca";

dgvDatos.Columns["columnPrecio"].DataPropertyName =

"Precio";

}

else

MessageBox.Show("No existen producto Registrado");

}

private void TraerPorId(int id)

{

try

{

_producto = _productoBol.TraerPorId(id);

if (_producto != null)

Page 79: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

{

txtId.Text = Convert.ToString(_producto.Id);

txtDescripcion.Text = _producto.Descripcion;

txtMarca.Text = _producto.Marca;

txtPrecio.Text = Convert.ToString(_producto.Precio);

}

else

MessageBox.Show("El Producto solicitado no existe");

}

catch (Exception ex)

{

MessageBox.Show(string.Format("Error: {0}", ex.Message),

"Error inesperado");

}

}

private void Eliminar(int id)

{

try

{

_productoBol.Eliminar(id);

MessageBox.Show("Producto eliminado satisfactoriamente");

TraerTodos();

}

catch (Exception ex)

{

MessageBox.Show(string.Format("Error: {0}", ex.Message),

"Error inesperado");

}

}

//

//

//Usamos nuestros metodos y funciones generales, observe como no

hemos repetido codigo en ningun lado

//haciendo con esto que nuestras tareas de actualizacion sean mas

sencillas para nosotros o para

//al asignado en realizarlas...

private void btnAgregar_Click(object sender, EventArgs e)

{

Guardar();

}

private void txtId_KeyDown(object sender, KeyEventArgs e)

{

Page 80: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

if (e.KeyData == Keys.Enter &&

!string.IsNullOrWhiteSpace(txtId.Text))

{

e.SuppressKeyPress = true;

TraerPorId(Convert.ToInt32(txtId.Text));

}

}

private void txtPrecio_KeyDown(object sender, KeyEventArgs e)

{

if (e.KeyData == Keys.Enter)

{

e.SuppressKeyPress = true;

Guardar();

}

}

private void btbnBuscar_Click(object sender, EventArgs e)

{

if (!string.IsNullOrWhiteSpace(txtId.Text))

{

TraerPorId(Convert.ToInt32(txtId.Text));

}

}

private void btnEliminar_Click(object sender, EventArgs e)

{

if (!string.IsNullOrWhiteSpace(txtId.Text))

{

Eliminar(Convert.ToInt32(txtId.Text));

}

}

}

}

De nuevo observe como esta capa desconoce si existe una capa de Datos y mucho menos que

motor de base de datos se utiliza, tampoco se encarga de implementar las reglas de validación ni

de lógica de negocio, su tarea es interactuar con el usuario pidiendo y desplegando información.

¿Que es lo que falta?

Solo nos resta probar el proyecto…pero eso, será tarea suya…Ejecute el proyecto, inserte un

nuevo registro, busque un registro por id, edite su información, elimine un producto, depure el

código línea a línea para viva de paso a paso como es que va pasando de capa de capa enviando

y trayendo información.

Page 81: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Aquí termina nuestro articulo sobre Arquitectura 3 Capas, espero haya sido de su agrado y que la

explicación haya sido lo bastante clara, en caso de que tenga alguna duda por favor deje su

pregunta en la sección de comentarios o escríbame por medio del formulario de contacto.

Escribir este articulo me llevo mas de 4 horas, dejar un comentario de agradecimiento le tomara 5

minutos.

Saludos desde Monterrey, Nuevo León México!

Ejemplo C#

App. Config, cadenas de conexión Hola a todos:

En este articulo haremos una incursión al archivo de configuración o App.Cofig para definir una

cadena de conexión a una Base de Datos:

Agregar un archivo de configuración a un proyecto

Definir una cadena de conexión a una Base de datos

Utilizar el archivo de configuración para obtener la cadena de conexión

Entrando en contexto..

Imagine, que hoy desarrolla un sistema con 20 Formularios, la cual va a instalar en 50 Pc‟s que

utilizaran para la administración de su empresa, su conocimiento sobre las ventajas de usar un

archivo de configuración es nula, así que usted uso lo que muchos programadores llegamos a

utilizar en nuestro inicios, establecer la cadena de conexión en cada método o función donde

necesitemos comunicarnos con la Bd, algo como esto:

C#:

using System.Data.SqlClient;

private void btnProbar_Click(object sender, EventArgs e)

{

using(SqlConnection cnx = new SqlConnection("Data Source=LUISESCOBAR-

PC;Initial Catalog=Directorio;Integrated Security=True"))

{

cnx.Open();

MessageBox.Show(cnx.State.ToString());

}

}

Vb.Net:

Page 82: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Private Sub btnProbar_Click(sender As System.Object, e As

System.EventArgs) Handles btnProbar.Click

Using cnx = New SqlConnection("Data Source=LUISESCOBAR-PC;Initial

Catalog=Directorio;Integrated Security=True")

cnx.Open()

MessageBox.Show(cnx.State.ToString())

End Using

End Sub

y para los que tienen mas experiencia pero aun no llegan a conocer los beneficios del archivo de

configuración, establecer la cadena de conexión en una variable global del tipo String podría

aparentar ser una buena solución ya que se asigna una sola vez y se usa en todas las consultas

requeridas.

C#:

using System.Data.SqlClient;

namespace sinAppConfig

{

public class Connection

{

public static SqlConnection Conexion()

{

return new SqlConnection("Data Source=LUISESCOBAR-PC;Initial

Catalog=Directorio;Integrated Security=True");

}

}

}

Usamos la clase Connection:

private void btnProbar_Click(object sender, EventArgs e)

{

//Utilizamos la clase connection para abrir la cadena de conexion

using(SqlConnection cnx = Connection.Conexion())

{

cnx.Open();

MessageBox.Show(cnx.State.ToString());

}

}

Vb.Net:

Imports System.Data.SqlClient

Module Module1

Page 83: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Public Function Connection() As SqlConnection

Return New SqlConnection("Data Source=LUISESCOBAR-PC;Initial

Catalog=Directorio;Integrated Security=True")

End Function

End Module

Usamos la función Connection declarado en el modulo Module1:

Public Class Form1

Private Sub btnProbar_Click(sender As System.Object, e As

System.EventArgs) Handles btnProbar.Click

'Usamos la funcion publica Connection declarada en el modulo

Module1

Using cnx = Connection()

cnx.Open()

MessageBox.Show(cnx.State.ToString())

End Using

End Sub

End Class

Bien, continuando con nuestro caso hipotético, imagínese que después de algún tiempo se le

notifica de la necesidad de modificar el nombre del server o la ubicación física del mismo, trayendo

con esto la necesidad de modificar nuestra cadena de conexión pero, como declaro su cadena de

conexión en alguna clase publica o modulo para los de Vb.net y esta clase o modulo se comprimió

junto con el Exe al momento de crear su installer ya no tiene acceso a ella desde fuera del

proyecto, así que no tendrá otra opción que abrir su proyecto desde el Vs y modificar su cadena de

conexión en el lugar donde lo haya declarado, si es en una clase publica o modulo solo tendrá que

modificar una sola vez pero, si declaro la cadena en cada método o función donde se requería la

comunicación con la Bd tendrá un problema mas grande (aunque no monstruoso), en realidad

modificar la cadena de conexión no será el problema puesto que usando la combinación de teclas

Ctrl + F podrá fácilmente buscarla y reemplazarla por la nueva.

El problema viene al momento de pasar esta actualización a todas las instalaciones de su

Software, ya que como sabrá, al momento de hacer la modificación tendrá que compilar de nuevo

los proyectos (el que contiene su desarrollo y el proyecto Setup) e ir a cada equipo donde su

software este instalado, desinstalar y posteriormente instalar de nuevo su software, este es el

verdadero problema ya que como se abra dado cuenta, no es tarea sencilla ya que la actividad no

se resume en una acción si no en varias, ahora si consideramos la disponibilidad de los usuarios

para dejarnos trabajar a nosotros mientras ellos se retrasan en sus actividades, estaremos en un

problema.

¿ Solución? usar el archivo de configuración….

Page 84: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Si utiliza un archivo de configuración no tendrá tantos problemas, ya que el utilizarlo simplifica la

tarea a únicamente ir al directorio de instalación ubicar el archivo App.Config, abrirlo con un editor

de texto como NotePad, modificar su cadena de conexión, guardar y listo a seguir usando su

aplicación sin mas ni mas; no necesita abrir el proyecto en el Vs ni compilar, mucho menos instalar

de nuevo.

¿Comprende ahora la gran utilidad de este archivo tan simple?…

Hasta este punto creo que ya esta convencidos de la utilidad del archivo de configuración, ahora

vayamos viendo como agregarlo a nuestro proyecto y como utilizarlo:

Agregar un archivo de configuración a un proyecto

En este ejemplo utilizaremos una Bd creada en SqlServer Express 2008 y Vs2010 Ultimate, la Bd

es únicamente para probar la conexión, puede crear cualquiera en su Server.

Antes de comenzar cree un proyecto del tipo Windows Forms, abra el formulario y agregue un

botón.

Para crear el archivo de configuración tenemos dos opciones:

Utilizar el “Asistente para la configuración de orígenes de base de datos” o insertar un nuevo

elemento al proyecto del tipo App.Config, veamos paso a paso cada uno de ellos,

Utilizar el “Asistente para la configuración de orígenes de base de datos”

Menú Datos –> Agregar nuevo origen de datos

Page 87: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

En esta parte, el asiste nos pregunta el nombre que asignaremos a la cadena de conexión,

podemos dejar el nombre por default o poner el nombre que creamos conveniente, en esta ocasión

dejemos el que nos pone por default mas adelante lo modificaremos:

Page 88: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Después de realizar todo lo anterior podrá ver en el “Explorador de soluciones” dos nuevos

archivos, que son el archivo de configuración y un DataSet:

El archivo DataSet por favor elimínelo, ya que no nos servirá de nada…

Si abre el archivo de configuración que acabamos de agregar a nuestro proyecto, podrá ver dentro

una estructura de código Xml como el siguiente:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<configSections>

</configSections>

<connectionStrings>

Page 89: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

<add

name="connectionString_CSharp.Properties.Settings.DirectorioConnectionStr

ing"

connectionString="Data Source=LUISESCOBAR-PC;Initial

Catalog=Directorio;Integrated Security=True"

providerName="System.Data.SqlClient" />

</connectionStrings>

</configuration>

Veamos que representa cada línea:

Esta línea representa el nombre de nuestra cadena de conexión, si recuerda en uno de los pasos

anteriores el asistente le preguntaba el nombre de la cadena de conexión, como dejamos el

nombre por default es este el que aparece como nombre de nuestra cadena:

<add name="connectionString_CSharp.Properties.Settings.DirectorioConnectionString"

Modifiquemos esta línea con el fin de tener un nombre mas corto (con este nombre será como

obtendremos el valor de nuestra Cadena):

<add name="cnxString"

La siguiente línea representa el valor de nuestra cadena de conexión:

connectionString="Data Source=LUISESCOBAR-PC;Initial

Catalog=Directorio;Integrated Security=True"

y por ultimo tendremos el nombre del motor de Base de Datos que estaremos usando:

providerName="System.Data.SqlClient" />

Bien, ya vimos como usar el asistente para definir una cadena de conexión…ahora vayamos a ver

Insertar un nuevo elemento al proyecto del tipo App.Config

Haga Click derecho sobre el proyecto –> Agregar –> Nuevo Elemento:

Page 90: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Seleccione “Archivo de configuración de aplicaciones”, deje el nombre por default y presione el

botón “Aceptar”

Observe que tenemos un nuevo archivo en el “Explorador de soluciones” ábralo dentro podrá ver

una estructura de código como la siguiente:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

</configuration>

Dentro de la etiqueta <configuration> usted tendrá que agregar el nombre de la cadena de

conexión, el valor de la cadena de conexión y el nombre del motor de Base de datos que estará

utilizando, esto ultimo no siempre es necesario ya que depende mucho del motor que estemos

utilizando porque para Bases de datos como Access, SqlCe…son necesarios para SqlServer no lo

es.

Al final usted deberá de tener un archivo con la siguiente estructura de código Xml:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<connectionStrings>

<add name="cnxString"

connectionString="Data Source=LUISESCOBAR-PC;Initial

Catalog=Directorio;Integrated Security=True"

providerName="System.Data.SqlClient" />

</connectionStrings>

</configuration>

Utilizar el archivo de configuración para obtener la cadena de conexión

Ahora veamos como utilizar la cadena de conexión que acabamos de crear por cualquiera de los

pasos anteriores.

Page 91: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

Antes de poder utilizar el valor de cadena de conexión almacenada en la

etiqueta connectionString de nuestro archivo de configuración, debe de agregar una referencia al

ensamblado System.Configuration para esto:

Haga click derecho sobre el proyecto –> Agregar referencia –> Ficha .Net –> seleccione

System.Configuration –> Aceptar

Una vez echo esto, vayamos a la clase donde queramos abrir la conexión e importemos el espacio

de nombres System.Configuration, echo lo anterior estamos listos para utilizar nuestro App.Config.

para C#:

using System;

using System.Windows.Forms;

using System.Data.SqlClient;

using System.Configuration;

namespace connectionString_CSharp

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void btnconectar_Click(object sender, EventArgs e)

{

TestConnection();

Page 92: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo

}

private void TestConnection()

{

using(SqlConnection cnx = new

SqlConnection(ConfigurationManager.ConnectionStrings["cnxString"].ToStrin

g()))

{

cnx.Open();

MessageBox.Show(cnx.State.ToString());

}

}

}

}

Para Vb.Net:

Imports System.Data.SqlClient

Imports System.Configuration

Public Class Form1

Private Sub btnProbar_Click(sender As System.Object, e As

System.EventArgs) Handles btnProbar.Click

TestConnection()

End Sub

Private Sub TestConnection()

Using cnx As New

SqlConnection(ConfigurationManager.ConnectionStrings("cnxString").ToStrin

g())

cnx.Open()

MessageBox.Show(cnx.State.ToString())

End Using

End Sub

End Class

Bien, cuando compile su proyecto, lo instale y se le presente la necesidad de modificar la cadena

de conexión, simplemente diríjase al directorio de instalación ubique el archivo de configuración

(una vez instalado su software la nomenclatura de su archivo

será NombredelProyecto.Exe.Config), ábralo con el notepad, modifique su cadena, guarde los

cambios y sin mas ni mas podrá seguir trabajando…

Saludos desde Monterrey, Nuevo León México!

Ejemplo C#

Ejemplo Vb.Net

Nota: El proyecto fue desarrollado en Vs2010 usando una Bd SqlServer 2008 Express y Framework 4.0 Client Profile

Page 93: ReportViewer y Rdlc, ejemplo Factura (datos fijos)docshare04.docshare.tips/files/24663/246633736.pdf · cuando no se tiene experiencia en el manejo de reportes tratare de que el articulo