Linq - Contenido Lenguaje Integrado de Consultas
Linq - Contenido Lenguaje Integrado de Consultas
2008
1. INTRODUCCION
1.1 Qu es LINQ?
En la actualidad las empresas que anhelan tener xito en el mercado deben implementar
Sistemas Informticos que les permitan intercambiar informacin con el mundo externo.
De ah comenzaron a surgir ideas para que las aplicaciones puedan comunicarse entres s.
Empezaron a aparecer los compiladores que tenan un lenguaje intermedio como .NET
que dispona del MSIL, JAVA tambin tena sus propios proyectos, etc. Y finalmente se
desarrollaron estndares para el envo y recepcin de los datos que necesitaban los
programas.
Sin embargo estos estndares tambin requieren tener una forma de conexin para
consultar y modificar los datos que en ellos se encuentran, lo que ocasionaba que los
desarrolladores tengan que aprender diferentes tipos de conexiones, diferentes
sentencias, e incluso trabajar con diferentes tipos de variables. Adicionalmente cuando se
tena que interactuar con fuentes de datos de dismiles tipos; el excesivo uso de variables
y conexiones poda ocasionar que las aplicaciones se hagan lentas y pesadas.
Pgina 1
2008
a los datos que se encontraban en las BD y otra manera diferente para acceder a las
fuentes o archivos XML.
ARQUITECTURA LINQ
Pgina 2
2008
LINQ a SQL es una extensin de ORM (Mapeador de Objetos Relacionales) que nos
permite modelar bases de datos relacionales con Visual Studio .NET 2008, permitiendo
consultar, agregar, modificar y eliminar registros de las bases de datos y tratarlas como si
fuesen clases del .NET.
Los programadores pueden utilizar LINQ con cualquier fuente de datos inclusive
consultando informacin que se encuentre en un determinado tipo de fuente, modificarla
en memoria y guardarla en otra fuente de datos.
EJEMPLO: Para hacer las declaraciones de los impuestos fiscales se podra escribir
sentencias LINQ que saquen informacin de las bases de datos relacionales y por medio
del mismo Lenguaje Integrado de Consultas generar los archivos XML que debern ser
enviados a las autoridades encargadas de recaudar estos valores.
Esto debido a que al escribir la sentencia LINQ no significa que los datos ya estn en
memoria, sino que estos son trados al momento de ejecutar las instrucciones en un bucle
foreach y por eso que es indispensable el uso de esta interfaz.
Investigadores: Tngl. Andrs Len O. - Ing. Jorge Ochoa
Pgina 3
2008
EJERCICIO 1 El siguiente ejemplo, presenta la lista de nmeros que sean menores al rango
que defina el usuario.
Nota: El hecho de crear la consulta no significa que ya dispongamos de los datos, sino es al
momento de ejecutar la misma en donde se puede obtenerlos y este proceso se realiza
precisamente en el bucle ForEach.
Pgina 4
2008
1.2 HISTORIA
Despus de dos dcadas, la industria ha alcanzado un punto estable en la evolucin de las
tecnologas de programacin orientada a objetos. Hoy en da los programadores estn
familiarizados con conceptos como las clases, objetos y mtodos. Analizando la
generacin de tecnologas actual y siguiente, se hace evidente que el siguiente gran reto
para la tecnologa de la programacin es reducir la complejidad del acceso e integrar la
informacin que no se define de manera nativa utilizando la tecnologa orientada a
objetos.
Pgina 5
2008
Utilizamos el trmino consultas integradas en los lenguajes para indicar que las consultas
son una caracterstica constituida en el framework que utiliza el lenguaje de programacin
principal del desarrollador (por ejemplo C# 3.0, Visual Basic 9). Las consultas embebidas
en los lenguajes permiten que las expresiones de consulta se beneficien de los metadatos
ricos, verificacin de sintaxis en tiempo de compilacin, tipado esttico y ayuda
IntelliSense que antes estaban disponibles solo para el cdigo imperativo. Las consultas
integradas en el framework que utilizan los lenguajes tambin hacen posible aplicar una
nica facilidad declarativa de propsito general a toda la informacin en memoria, y no
solo a la informacin proveniente de fuentes externas.
Las consultas integradas en el framework 3.0 para los lenguajes de Visual Studio .NET
2008 definen un conjunto de operadores de consulta estndar de propsito general que
hacen posible que las operaciones de recorrido, filtro y proyeccin sean expresadas de
una manera directa pero declarativa en cualquier lenguaje de programacin. Los
operadores de consulta estndar permiten aplicar las consultas a cualquier fuente de
informacin basada en IEnumerable<T>. LINQ permite que terceros fabricantes aumenten
el conjunto de operadores de consulta estndar, aadiendo los operadores de dominio
especfico que sean apropiados para el dominio o la tecnologa de destino. Ms
importante an es que terceros fabricantes tambin pueden reemplazar los operadores
de consulta estndar con sus propias implementaciones que ofrezcan servicios adicionales
como la evaluacin remota, traduccin de consultas, optimizacin, etc. Al adherirse a los
Pgina 6
2008
Pgina 7
2008
Pero si la empresa requiere compartir informacin con otras instituciones que utilizan los
mismos datos pero diferentes aplicaciones e inclusive diferentes bases de datos entonces
lo debe hacer a travs de algn estndar como XML. LINQ, hace que todo este proceso
que antes era muy laborioso para los desarrolladores se simplifique considerablemente ya
Pgina 8
2008
que con una misma sintaxis se conecta a su base de datos, obtiene la informacin que
necesita, crea los documentos XML, registra el contenido y lo puede enviar.
La tecnologa LINQ puede ser utilizada tanto para ambientes de oficina como para
desarrollar aplicaciones Web, es decir que el programador no solo que podr hacer uso de
los procedimientos almacenados, sino que tambin lo puede combinar con los beneficios
que nos brinda los servicios web e incluso una arquitectura SOA que este bien
implementada. Aclarando que SOA no son Servicios Web, por el contrario los Servicios
Web son tan solo una parte de la Arquitectura SOA.
AND
OR
Se representa con ||
Las consultas combinadas en LINQ se realizan a travs de las claves externas que se
representa en el modelo como propiedades que tienen una coleccin de elementos, pero
Investigadores: Tngl. Andrs Len O. - Ing. Jorge Ochoa
Pgina 9
2008
tambin aunque no muy a menudo se puede utilizar el operador JOIN siempre y cuando se
est trabajando con colecciones de objetos, que a diferencia de SQL se lo hace con tablas.
Es tan extenso las clusulas SELECT, GROUP, ORDER, etc. Que para poder explotar todo el
potencial que estas nos ofrecen deberamos realizar un estudio a fondo de cada una de
ellas pudiendo ser solo esta clusula tema de una monografa completa.
var Bandera=false;
var Nombre=Mariana;
Pgina 10
2008
Los mtodos annimos aparecieron desde C# 2005 con el Framework 2.0 y estaban
pensados para facilitar la definicin de manejadores de eventos cuando las tareas a
realizar son simples.
Pgina 11
2008
Las expresiones lambda son propias de C# 3 y nos permiten hacer lo mismo que los
mtodos annimos pero de una forma ms sencilla. Una de las caractersticas de las
expresiones lambda es el signo lambda que se representa con =>.
Esta forma de programar abre la posibilidad de que nuestros programas llamen a otros
programas, podemos utilizar a lambda como entidades de cdigo o de datos y son de
mucha utilidad al momento de escribir instrucciones LINQ.
Pgina 12
2008
// System.Collections.Generic
public interface IEnumerable<T> : IEnumerable{IEnumerator<T> GetEnumerator();}
// System.Collections
public interface IEnumerable{IEnumerator GetEnumerator();}
// System.Collections.Generic
public interface IEnumerator<T> : IDisposable, IEnumerator
{
T Current { get; }
}
// System.Collections
public interface IEnumerator
{
object Current { get; }
void Reset();
bool MoveNext();
}
Pgina 13
2008
Por qu IEnumerable?
Toda consulta LINQ que escribamos contiene el cdigo que se va a ejecutar para consultar
o modificar los datos que tenemos en las diferentes fuentes. Pero la consulta solo se
ejecutar el momento en que se ejecute el bucle foreach.
XMLReader permite leer archivos XML sin realizar la carga en cach y evitando la lectura
de los nodos no deseados. Es una clase abstracta que se encuentra en el namespace
System.Xml.
Pgina 14
2008
Estas clases ofrecen un alto potencial para trabajar con informacin contenida en
formatos xml, por lo que un programador que conozca el funcionamiento XMLReader,
XMLWritter y LINQ, si combina todas estas herramientas estar en capacidad de escribir
cdigo potente y gil para realizar consultas, modificar documentos y a travs de este
formato intercambiar informacin con otras aplicaciones.
XSD, no tiene una definicin comn para sus siglas pero respecto al significado de su
funcionalidad todos concuerdan que es un lenguaje que nos da una mejor visin de la
estructura de los documentos XML con lo que vamos a trabajar.
Pgina 15
2008
EJEMPLO: Cuando solicitamos al usuario que ingrese la cdula la recibimos como una
cadena. Si nosotros utilizamos mucho el proceso de validacin de cdula entonces al
implementar este mtodo como una extensin de la clase string cada vez que declaremos
una variable de este tipo aparecer nuestro mtodo como uno ms de la clase.
Pgina 16
2008
Visual Studio proporciona herramientas en tiempo de diseo para crear y editar los
orgenes de datos que va a utilizar en su aplicacin, en los proyectos de Visual Studio los
orgenes de datos se representan como conjuntos de datos u otros tipos de objeto,
dependiendo de los objetos que devuelva el almacn de datos subyacente.
LINQ a SQL.- Permite la conexin con bases de datos SQL Server, es como si este
motor tuviera una funcionalidad del Lenguaje Integrado de consultas dedicada
exclusivamente para l.
LINQ a Entidades.- Permite que la aplicacin se conecte con bases de datos que
nos sean SQL Server.
LINQ a DataSet.- tambin conocido como LINQ a objetos, que admite realizar las
mismas operaciones que normalmente se hacen con las bases de datos con
objetos DataSet y DataTable.
Pgina 17
2008
Nota: Debido a lo extenso que es la tecnologa LINQ, en esta investigacin haremos una
introduccin a las dos primeras formas de conexin. Explicando cmo LINQ las define y
trabaja con cada una de ellas y en los siguientes captulos se harn ejemplos de consultas
(SELECT), tambin haremos operaciones de insertar, editar y eliminar datos (INSERT,
UPDATE, DELETE y finalizaremos indicando como ejecutar procedimientos almacenados
desde LINQ.
LINQ a XML no es otra cosa que proporcionar toda la potencialidad del Lenguaje
Integrado de Consultas aplicado a la informacin que se encuentra contenida en este
formato, permitindonos leer y modificar estos archivos de forma parecida a como lo
hacamos en versiones anteriores de .Net a travs de XMLReader y XMLWritter pero con
una notable mejora en el consumo de memoria y la cantidad de cdigo que debemos
escribir para obtener los mismos resultados, adicionando la ventaja que con esta nueva
tecnologa podemos conectarnos y trabajar con otras fuentes de datos que a diferencia de
Pgina 18
2008
las clases que se utilizaban en versiones anteriores para trabajar con XML son nica y
exclusivamente para este formato.
Proporciona una identificacin a los nodos de los archivos XML.- Podemos dar un nombre
a cada elemento de nuestro rbol XML a travs de la propiedad XName, esta utilidad ser
de gran ayuda al momento de realizar copias, reemplazos o al renombrar los Nodos.
Creacin de estructuras XML.- El Ejercicio 1 expone la gran facilidad con la que se puede
crear estructuras XML a travs del Lenguaje Integrado de Consultas.
Investigadores: Tngl. Andrs Len O. - Ing. Jorge Ochoa
Pgina 19
2008
Acceso a datos.- Permite leer y modificar los nodos de los archivos XML con sentencias
muy similares a SQL y tomando en cuenta que LINQ tambin implementa conectividad con
bases de datos los desarrolladores pueden consultar las dos fuentes con una misma
sintaxis.
Elementos principales.- Los elementos bsicos para trabajar con formatos XML a nuestro
criterio son XElement y XAttribute. Aunque otros desarrolladores tambin incorporan a
XName, nosotros hemos preferido no hacerlo. Como ya hemos explicado antes XName es
una gran innovacin pero respaldados en los ejercicios que se han desarrollado en esta
investigacin creemos que no se lo debe tratar como un elemento bsico de LINQ.
EJERCICIO 1
Crear un archivo XML, que contenga la informacin bsica de una persona. Para poder
probar el ejercicio deber crear un formulario con dos botones el uno para la forma
Pgina 20
2008
Cdigo: Este ejercicio tiene como finalidad introducir al lector a la funcionalidad que implementa LINQ a
XML, para esto hemos creado dos veces el mismo archivo, la diferencia en la cantidad y la complejidad del
cdigo resalta a la vista. Esto se profundizar cuando estudiemos la clase XElement y XAttribute que son dos
de los pilares de la funcionalidad XML.
Pgina 21
2008
Es muy importante recalcar que LINQ tambin incorpora Intellisence, lo que significa que
el mismo compilador nos permitir detectar errores de sintaxis en la construccin de
consultas.
Pgina 22
2008
Compatibilidad con espacios en blanco.- Los espacios en blanco siempre han significado un
problema al momento de desarrollar cdigo para leer, cargar o editar archivos XML, con
LINQ a XML podemos tratar los espacios atravs de nodos texto conocidos como xText.
Control simplificado de nombres y espacios de nombres.- Evita tener que manejar espacios
de nombres o prefijos de espacios de nombres, es decir si el desarrollador desea los podr
hacer uso, caso contrario al momento de la serializacin se definir los prefijos.
As mismo para cambiar el nombre de un nodo XML, se deba crear un nodo con diferente
nombre y copiar todo el contenido del nodo original. En cambio LINQ soluciona este
problema apoyndose en la propiedad xName de los nodos.
Diferencias entre LINQ a XML y XML Reader.- XML Reader nos permite realizar lecturas
de documentos XML, pero ser el programador quien deba analizar y decidir que va a
utilizar.
A lo que queremos hacer referencia es que en muchas ocasiones no es suficiente solo leer
los orgenes de datos, es ms, tal vez ni siquiera haya un nico origen de datos entonces
Investigadores: Tngl. Andrs Len O. - Ing. Jorge Ochoa
Pgina 23
2008
los que nos toca es tomar los datos de las diferentes fuentes luego darles el tratamiento
necesario y generar un resultado. En este caso ser de mucha utilidad el Lenguaje
Integrado de Consultas, o podra tambin ser una combinacin entre XMLReader y las
bondades que nos ofrece LINQ.
Los elementos difieren de los atributos en el aspecto que los ltimos no son nodos, ms
bien podramos decir que estos son parte de los nodos y que estn compuestos por dos
valores, uno que representa el nombre del atributo y el segundo que indica el contenido
del atributo.
Por otra parte la clase XDocument si bien forma parte de LINQ, lo mejor es saber
analizarlo de manera correcta, ya que en muchas ocasiones resulta ms facil manejar
archivos unicamente con elementos y atributos.
Pgina 24
2008
Cuando utilizamos la clase XDocument debemos tomar en cuenta que un documento solo
puede tener un elemento secundario, siendo este el nodo riz. No cambia mucho o quiz
nada, ya que todo documento XML requiere que el nodo principal sea nico.
As mismo hay otros elementos que puede tener un documento XML, como son
XDeclaration, XProcessingInstruction, XComment, XDocumentType, etc. La clase
XDocument se deriva de Container por lo que su funcion es similar a la de un contenedor.
El aprendizaje de estas tres clases es muy sencillo ya que la mayora de mtodos que
implementan cada una de ellas son muy similares entre s. Ejemplo:
XElement elemento =
new XElement("MiElemento",
new XAttribute("MiAtributo", "12"));
Cdigo: Este es uno de los paso fundamentales para poder crear estructuras XML, en este ejemplo hemos
creado un nodo XElement y le asignado un solo atributo, al leer el cdigo podemos darnos cuenta que
instanciamos un objeto XElement, el primer parmetro es el nombre y el segundo es vector que puede tener
uno o varios atributos o incluso subnodos. Lo nico que debemos tomar en cuenta es anteponer la palabra
new a cada elemento o atributo que se crea.
En el ejemplo podemos ver que tanto la clase XElement como XAttribute son similares,
XElement recibe de parmetros el nombre del elemento en este caso MiElemento y como
segundo parmetro los atributos de cada elemento. En cambio XAttribute recibe el
nombre del atributo y en segundo lugar el valor o contenido del atributo.
Para el caso de los Documentos XDocument funciona de manera muy similar a las dos
clases anteriores, pero esta recibe parametros como: XComent, XProcessingInstruction,
XDeclarative, XElement, etc. Segn la instancia que se utilice.
Pgina 25
2008
Cdigo: La primera lnea carga el documento XML en un objeto XElement y la segunda carga el mismo
documento pero en un objeto XDocument.
Cuando deseamos realizar la carga de un documento XML con algunas restricciones como
por ejemplo preservar los espacios en blanco, podemos enviar el parmetro LoadOptions
indicando como se debe realizar la carga. En el ejemplo siguiente vamos a cargar el
documento ConLINQ.xml preservando los espacios en blanco. Igual que el ejemplo
anterior es la misma sintaxis tanto para XElement como para XDocument.
XDocument MiArchivo = XDocument.Load("d:\\ConLINQ.xml",LoadOptions.PreserveWhitespace);
Cdigo: El segundo parmetro del metodo Load() indica que debe preservar los espacios en blanco
Pgina 26
2008
EJERCICIO 2
En este ejercicio vamos a cargar el archivo XML ConLINQ.xml que creamos al principio de
este tema y despes vamos a presentar el nombre del contacto.
XElement Contacto = XElement.Load("d:\\ConLINQ.xml");
IEnumerable<XElement> NodosHijo = from persona
in Contacto.Elements()
select persona;
foreach (XElement persona in NodosHijo)
MessageBox.Show("Nombre: " + persona.NextNode.ToString());
Cdigo: La instruccin de consulta carga todos los subnodos del nodo Contactos (NodoRaiz) y luego a travs
del bucle foreach los va presentando de uno en uno, anteponiendo la palabra nombre
Nota: Recomendamos ampliar el archivo XML por los menos a tres contactos para
entender mejor el cdigo.
Basado en ORM LINQ, permite realizar un mapeo de la base de datos con la que se desea
trabajar cargando dentro de este mapa tanto las tablas como los procedimientos
almacenados que vamos a necesitar. A partir de esto se puede comenzar a escribir
instrucciones de lectura y de escritura en las entidades que fueron cargadas en nuestra
clase.
Investigadores: Tngl. Andrs Len O. - Ing. Jorge Ochoa
Pgina 27
2008
Una vez que hemos explicado cual es la funcionalidad de LINQ a SQL comenzaremos a
realizar algunos ejemplos que no permitirn entender mejor como se puede implementar
esta beneficio del nuevo lenguaje de consultas.
Lo primero que debemos hacer es agregar un nuevo elemento de la misma forma que si
estuvieramos agregando un formulario o una clase pero en el cuadro de dilogo que se
presenta para que seleccionemos el elemento que vamos a adicionar a nuestro proyecto
debemos escoger la opcion LINQ a SQL clase que tiene una extension .dbml como se ve
en la siguiente figura:
Pgina 28
2008
Ahora debemos crear una conexin a la base de datos con la que deseamos trabajar para
poder arrastrar las tablas y procedimientos almacenados que vayamos a manipular en
nuestra aplicacin.
Como se podr observar cuando hagamos el mapeo de nuestra base de datos. LINQ no fue
creado para reemplazar a los Procedimientos Almacenados sino mas bien para
complementar su funcionalidad. Desde LINQ el desarrollador puede llamar y ejecutar
todos los PA que necesite su aplicacin.
Pgina 29
2008
LINQ, toma las sentencias que escribimos en nuestros programas las interpreta y
convierte a una consulta SQL (En lo que respecta a LINQ a SQL) y lo ejecuta contra la base
de datos.
Tambin si ejecutamos un programa que contenga cdigo LINQ paso a paso, veremos que
despus de creada la consulta esta es una instruccin SQL, por lo que se convierte en un
proceso similar a escribir sentencias SQL dentro del cdigo de la aplicacin. Y los
Procedimientos Almacenados?. Si personalmente creemos que aunque utilicemos LINQ
deberamos conectarnos a la base de datos con PA que estn cargados en el contexto y
dejar las consultas para los objetos DataSet y archivos XML.
Investigadores: Tngl. Andrs Len O. - Ing. Jorge Ochoa
Pgina 30
2008
En conclusin podramos decir que LINQ funciona como un intrprete de las transacciones
que nosotros escribimos en el cdigo de nuestro programa convirtindolas a T-SQL,
XQuery, etc. Segn cul sea la fuente de datos a la que se est conectando.
2.3 Qu es ORM?
Mapeo de objetos Relacionales (Object Relational Model)
Es importante aclarar que LINQ no es un ORM, sino mejor se apoya en los ORM para
implementar sus funcionalidades conocidas como LINQ a SQL y LINQ a Entidades que
tambin debemos indicar son diferentes. La primera es orientada especficamente para
bases de datos que se encuentran almacenadas en un motor de SQL Server mientras que
la segunda hace la misma funcin que la anterior pero con bases de datos que no se
encuentran en SQL Server.
Cuando mapeamos la base de datos podemos acceder a todas las tablas y procedimientos
almacenados que se hayan incluido en el mapa como si fueran clases del software que se
est construyendo. As tambin estas clases podrn ser instanciadas y por lo tanto
tambin tendrn propiedades y mtodos ajustados a cada una de ellas.
Pgina 31
2008
El ORM al que nos referimos se conoce especficamente como LINQ a SQL. Esta es solo
una de las variantes de LINQ, puesto que el mismo puede utilizarse con otros orgenes de
datos, como por ejemplo XML y objetos. En s, LINQ brinda el poder de hacer todo tipo
de querys en el lenguaje de nuestra preferencia (Visual Studio .Net 2008), contra cualquier
origen de datos, transformar (opcionalmente) los datos a la forma que uno desee y luego
manipular fcilmente los resultados.
Pgina 32
2008
En el grfico anterior podemos observar como hemos creado la conexin a nuestra base
de datos atravs del explorador de servidores (parte izquierda del grafico), en el centro se
encuentran las tablas que hemos agregado a nuestra clase LINQ a SQL, en esta misma
zona podemos colocar las vistas en caso de haberlas y en la parte derecha colocamos los
procedimientos almacenados tal como se muestra en el grfico superior.
Guardamos los cambios realizados en nuestra aplicacin. Para terminar debemos hacer
una instancia de nuestro ORM que tenemos creado. Esto se realiza de la siguiente forma:
Pgina 33
2008
Absolutamente todas las entidades de la base de datos que deseamos utilizar con
consultas LINQ debern estar cargadas en el esquema de Base de datos. Podemos seguir
agregando ms entidades despus de que hayamos creado el esquema con tan solo
arrastrarlas y soltarlas dentro del contexto.
Es importante aclarar que para conectarse con otros motores de base de datos a travs
del Lenguaje Integrado de Consultas se debe realizar a travs de LINQ a Entidades.
La siguiente instruccin permite cargar todos los clientes de nuestra base de datos y
presentarlos en una grilla.
public void BuscarCliente()
{
var Consulta=from cliente in MiEsquema.Cliente select cliente;
grilla.DataSource = Consulta;
}
Pgina 34
2008
Ejercicio 3
Este ejemplo ha sido tomado de MSDN, lo que debemos hacer es crear el archivo xml en la
unidad D:, el cdigo es el siguiente:
<?xml version="1.0" encoding="utf-8" ?>
<Report>
<Section>
<Heading>
<Column Name="CustomerId">=Customer.CustomerId.Heading</Column>
<Column Name="Name">=Customer.Name.Heading</Column>
</Heading>
<Detail>
<Column Name="CustomerId">=Customer.CustomerId</Column>
<Column Name="Name">=Customer.Name</Column>
</Detail>
</Section>
</Report>
Pgina 35
2008
Cdigo: Creamos una sentencia LINQ en donde cargue todos los nodos descendientes del documento que
llamamos en donde el valor del mtodo ValorPresentar() que se construir a continuacin empiece con la
letra C.
Despus de la llave que cierra la clase del formulario creamos una clase esttica con el
siguiente cdigo:
public static class MiExtension
{
public static string ValorPresentar(this XElement xe)
{
return xe
.Nodes()
.OfType<XText>()
.Aggregate(new StringBuilder(),
(k, j) => k.Append(j),
k => k.ToString());
}
}
Ejercicio tomado de la ayuda de MSDN.
Cdigo: El cdigo anterior extrae los nodos del elemento que estamos procesando que sean de tipo texto a
travs del mtodo OfType(). Y estructura la cadena resultado a travs de mtodo Agregate que recibe tres
parmetros:
El primero es un string builder en donde construiremo el valor resultante de todos los nodos hijos
que nos devuelva la sentencia.
El segundo es una expresion lambda que concatena cada valor extraido a partir del mtodo
Append() a la cadena que creamos en el paso anterior.
El tercero es una cadena que necesita el mtodo agregate para presentar el resultado, la expresion
lambda hace la asignacion
Pgina 36
2008
EJERCICIO 4
XElement archivo = XElement.Load("D:\\ConLINQ.xml");
IEnumerable<string> texto =from elemento in archivo.Descendants("Nombre")
select (string)elemento;
string Resultado = texto.Aggregate(new StringBuilder(),
(ArmarCadena,ValorNodo ) => ArmarCadena.Append(ValorNodo+"; "),
CadenaFinal => CadenaFinal.ToString().Trim());
MessageBox.Show(Resultado, "Elemento encontrado");
Cdigo: Cargamos nuestro documento XML, luego escribimos la consulta LINQ, indicando que nos devolver
los nodos hijos a travs del mtodo Descendants() y pasando como parmetro el nombre del nodo padre. En
el select hacemos un cast a string del elemento que nos devuelve la consulta.
Agregate.- al valor que nos devolvi la instruccin le ejecutamos el mtodo Agregate() que recibe tres
parmteros:
El primero es un string builder en donde construiremos el valor resultante de todos los nodos hijos
que nos devuelva la sentencia.
El segundo es una expresion lambda que concatena cada valor extrado a partir del mtodo
Append() a la cadena que creamos en el paso anterior.
El tercero es una cadena que utiliza el mtodo Agregate() para presentar el resultado, la expresin
lambda hace la asignacion.
Finalmente se presenta el resultado al usuario a travs de un cuadro de dilogo.
<Tests>
<Test TestId="0001" TestType="CMD">
<Name>Convert number to string</Name>
<CommandLine>Examp1.EXE</CommandLine>
<Input>1</Input>
<Output>One</Output>
</Test>
<Test TestId="0002" TestType="CMD">
<Name>Find succeeding characters</Name>
<CommandLine>Examp2.EXE</CommandLine>
<Input>abc</Input>
<Output>def</Output>
</Test>
<Test TestId="0003" TestType="GUI">
<Name>Convert multiple numbers to strings</Name>
<CommandLine>Examp2.EXE /Verbose</CommandLine>
<Input>123</Input>
<Output>One Two Three</Output>
</Test>
Investigadores: Tngl. Andrs Len O. - Ing. Jorge Ochoa
Pgina 37
2008
Cdigo: Cargamos nuestro documento XML, Hacemos una consulta que filtre solo los nodos que tengan el
atributo CommandLine=Examp2.EXE (ver la estructura del archivo XML creado para entender mejor el
atributo CommandLine). Presentamos los resultados de la consulta atravs del bucle foreach.
Pgina 38
2008
Comenzaremos haciendo unos ejercicios que nos permitan cargar informacin de nuestra
base de datos a travs de la clusula Select, de la misma forma que hicimos con los
archivos XML, realizaremos varios ejemplos que realicen consultas de diferentes formas y
al final de cada ejemplo se har una pequea explicacin del cdigo fuente.
Pgina 39
2008
Cdigo: La consulta obtiene todos los registros de la entidad de clientes, en el bucle foreach asignamos el
nombre de cada elemento al texto que pasamos como parmetro, al ejecutar el programa quedar
visualizando el ltimo registro en el texto, tambin se devuelve la consulta para asignar como DataSource de
la grilla.
Ejercicio 7
var Consulta = from cliente in MiEsquema.Cliente
where cliente.NomCli.StartsWith("D") ||
cliente.NomCli.StartsWith("J")
select cliente;
foreach (var elemento in Consulta)
{
texto.Text = elemento.NomCli;
}
return Consulta;
Cdigo: Se diferencia del ejercicio anterior porque la consulta implementa una condicin where para que
visualice los registros en los que el nombre del cliente empiece con las letras C o J.
Pgina 40
2008
Ejercicio 8
public IQueryable LitaOrdenadaASC()
{
var Consulta = from cliente in MiEsquema.Cliente
orderby cliente.NomCli ascending
select cliente;
return Consulta;
}
public IQueryable LitaOrdenadaDSC()
{
var Consulta = from cliente in MiEsquema.Cliente
orderby cliente.NomCli descending
select cliente;
return Consulta;
}
Cdigo: Tenemos 2 mtodos el primero presenta el listado de clientes que tenemos ordenado en forma
ascendente de acuerdo al nombre, y el segundo presenta ordenado de forma descendente, lo nico que
cambia es la palabra clave ascending o descending, en caso de que no se indique la forma de ordenamiento
el compilador por defecto asumir que es ascendente.
Ejercicio 9
public void ContarRegistros()
{
string Informe = "Se ha contado los registros que tienen las entidades Clientes y
Productos. \n Los resultados fueron: \n" +
"\t\tCliente: " + MiEsquema.Cliente.Count().ToString() + " registros\n" +
"\t\tProductos: " + MiEsquema.Producto.Count().ToString() + " registros";
MessageBox.Show(Informe,"Informe:",MessageBoxButtons.OK,MessageBoxIcon.Information);
}
Cdigo: El cdigo es muy facil de comprender, consiste en crear una cadena y concatenar el texto que se va a
presentar para indicar al usuario el resultado del proceso y la parte LINQ es solo la instancia del nuestro
contexto con el nombre de la entidad y llamamos al mtodo Count() para que nos devuelva el nmero de
registros.
Pgina 41
2008
Para facilitar el entendimiento del cdigo vamos a crear los siguientes dos mtodos de la
entidad producto en nuestra clase cliente, para obtener el costo promedio de los precios
que tienen nuestra mercadera.
EJERCICIO 10
System.Nullable<Decimal> Promedio = (from prom in MiEsquema.Producto
select prom.PrePrd).Average();
MessageBox.Show("El costo promedio de los productos es: " +
Promedio.ToString(),"Calcular Promedio");
Cdigo: Construimos la consulta LINQ entre parentesis y despus de la palabra clave select seleccionamos la
propiedad precio (prom.PrePrd) despues cerramos el parentesis y llamamos al mtodo Average()
que calcula el promedio y devuelve un valor decimal. Finalmente presentamos el resultado en un
cuadro de dilogo.
Ejercicio 11
public void SumaPrd()
{
System.Nullable<Decimal> Suma = (from prom in MiEsquema.Producto
select prom.PrePrd).Sum();
MessageBox.Show("La suma de los precios de los productos es: " + Suma.ToString(),
"Calcular Suma");
}
Cdigo: Es el mismo proceso que el clculo del promedio, unicamente cambiamos la llamada al mtodo
Average() por el mtodo Sum().
Pgina 42
2008
Cdigo: La consulta de este ejercicio agrupa, ordena y seleciona los campos que vamos a presentar en el
resultado.
1- Indicamos la variable de iteracion (prod) y el origen de datos (MiEsquema.Productos)
2- Escribimos la palabra clave group seguido de la variable de iteracion que le informa al compilador
que se va a agrupar, despus digitamos la palabra reservada by seguido de los campos por los que
vamos a agrupar. En el caso de ser ms de un campo se debera hacer (new {campo1, campo2,
campo3}.
3- A esto concatenamos la palabra into con un nombre de grupo (g).
4- Ordenamos los resultados.
5- Para terminar indicamos que campos deseamos visualizar atravs de la sentencia select, con la
diferencia que ahora en lugar de la variable de iteracion ponemos el nombre del grupo. Todos los
campos que se seleccionen debern estar agrupados o ser parte de una funcion de agrupacin.
Los resultados se presentan atravs del bucle foreach en donde preguntamos si el estado es true el grupo
esta activo caso contrario est descontinuado. Se forma la cadena y lo presentamos en la cuadro de dilogo.
El cdigo del formulario para llamar a los mtodos que hemos creado en nuestra clase
cliente estara de la siguiente forma:
private void btnSeleccionar_Click(object sender, EventArgs e)
{
dtgResultado.DataSource = objCliente.ListarCliente(txtTexto);
}
private void btnOrdenar_Click(object sender, EventArgs e)
{
dtgResultado.DataSource=objCliente.LitaOrdenadaASC();
//dtgResultado.DataSource = objCliente.LitaOrdenadaDSC();
}
private void btnContar_Click(object sender, EventArgs e)
{
objCliente.ContarRegistros();
}
private void btnPromedio_Click(object sender, EventArgs e)
{
objCliente.PromedioPrd();
}
private void btnSumar_Click(object sender, EventArgs e)
{
objCliente.SumaPrd();
}
Investigadores: Tngl. Andrs Len O. - Ing. Jorge Ochoa
Pgina 43
2008
Cdigo: Solo son llamadas a los mtodos que hemos creado en la clase cliente. En el botn ordenar podemos
ver una lnea en comentario, esto para que se ejecute el orden ascendente, luego comentamos el llamado al
orden ascedente y ejecutamos el llamado descendente.
Consecuentemente nos faltara hacer el ejercicio que haga un AGE (Actualizar, Guardar y
Eliminar) a los datos de estos orgenes XML utilizando el potencial de LINQ a XML para
esto crearemos un pequeo formulario como se muestra en la siguiente figura:
EJERCICIO 13
Pgina 44
2008
En el evento click del botn de crear archivo escribiremos el siguiente cdigo a travs del
cual creamos nuestra estructua XML con la que desarrollaremos todo nuestro ejemplo:
try
{
XNamespace EN = "Espacio de Nombre";
XDocument MiDocumento =
new XDocument(
new XComment("Archivo XML que va a ser modificado"),
new XElement("Listado",
new XElement("Registro",
new XElement("Codigo", 1),
new XElement("Nombre", "Francisco Jos Ochoa Castillo"),
new XElement("Telefono", "2800600")
),
new XElement("Registro",
new XElement("Codigo", 2),
new XElement("Nombre", "Martha Florinda Iiguez Santilln"),
new XElement("Telefono", "2800601")
)
)
);
MiDocumento.Save("d:\\EjemploAGE.xml");
MostarArchivo("Archivo creado:");
}
catch
{ MessageBox.Show("No se ha podido crear el archivo. Por favor vuelva a
intentar", "Crear archivo", MessageBoxButtons.OK, MessageBoxIcon.Error); }
Cdigo: Creamos el archivo XML para poder realizar las operaciones de agregar, modificar y eliminar.
Podemos observar que en la primera linea hemos utilizado la clase XNameSpace, esta clase permite asignar
un espacio de nombre al archivo XML que estamos creando. Tambin podemos notar que despus de hacer
la instancia del documento utilizamos la clase XComment que agrega un comentario al documento XML.
El siguiente paso consiste en crear una enumeracin y luego dos mtodos el primero que
ser el encargado de agregar, modificar, y eliminar nuestro documento xml:
public enum opciones { Agregar, Modificar, Eliminar };
private void LINQAGEXML(opciones Accion)
{
try
{
DocXML = XDocument.Load("d:\\EjemploAGE.xml");
switch (Accion)
{
case opciones.Agregar:
XElement NuevoRegistro = new XElement("Registro",
new XElement("Codigo", txtCodigo.Text),
new XElement("Nombre", txtNombre.Text),
new XElement("Telefono", txtTelefono.Text));
DocXML.Element("Listado").Add(NuevoRegistro);
DocXML.Save("d:\\EjemploAGE.xml");
break;
case opciones.Modificar:
var CargarNodo = from NodoAnterior in DocXML.Descendants("Registro")
where NodoAnterior.Element("Codigo").Value == txtCodigo.Text.Trim()
select NodoAnterior;
Investigadores: Tngl. Andrs Len O. - Ing. Jorge Ochoa
Pgina 45
2008
CargarNodo.ElementAt(0).ReplaceAll(
new XElement("Codigo", txtCodigo.Text),
new XElement("Nombre", txtNombre.Text),
new XElement("Telefono", txtTelefono.Text));
DocXML.Save("d:\\EjemploAGE.xml");
break;
case opciones.Eliminar:
var EliminarNodo = from NodoEliminar in DocXML.Descendants("Registro")
where NodoEliminar.Element("Codigo").Value == txtCodigo.Text
select NodoEliminar;
EliminarNodo.Remove();
DocXML.Save("d:\\EjemploAGE.xml");
break;
}
MostarArchivo("Transaccion compleatada. El nuevo archivo es:");
}
catch
{
MostarArchivo("No se pudo completar
encuentra de la siguiente forma:");
la
transaccion.
El
archivo
actualmente
se
}
}
Cdigo: Instanciamos y cargamos nuestro archivo con el mtodo Load(). Creamos un switch() que clasificr
las opciones de AGREGAR, MODIFICAR o ELIMINAR.
Agregar.- Creamos la estructura que se va a adicionar en nuestro caso a travs de la clase
XElement instanciada con el nombre de Nuevo Registro. Terminada de crear la nueva estructura la
implementamos a travs del mtodo Add() y finalmente guardamos el documento con el mtodo
Save().
Modificar.- A travs de una consulta LINQ, colocamos en la variable CargarNodo el elemento
XElement que va a ser modificado, despus con el mtodo ReplaceAll(), reemplazamos los nuevos
valores del nodo y guardamos el documento con el mtodo Save().
Eliminar.- As mismo con una consulta LINQ cargamos el nodo que va a ser eliminado. En nuestro
caso se llama EliminarNodo. El proceso de eliminar se realiza a travs del mtodo Remove(), y de
igual forma que en guardar y actualizar guardamos el documento con el mtodo Save().
private void MostarArchivo(string Texto)
{
MessageBox.Show(Texto+"\n" + DocXML.ToString(), "Transaccion LINQ");
}
Finalmente solo nos falta hacer la llamada en los botones de Nuevo, Agregar y Eliminar
private void btnAgregar_Click(object sender, EventArgs e)
{
LINQAGEXML(opciones.Agregar);
}
private void btnModificar_Click(object sender, EventArgs e)
{
LINQAGEXML(opciones.Modificar);
}
private void btnEliminar_Click(object sender, EventArgs e)
{
LINQAGEXML(opciones.Eliminar);
}
Pgina 46
2008
Tenemos cuatro cajas de texto en las que podemos ingresar el cdigo, nombre, direccin y
telfono del cliente; tres botones de edicin: guardar, modificar y eliminar. Adems
disponemos de una grilla en la parte inferior que nos permita visualizar el resultado de las
transacciones que vayamos realizando.
En los ejercicios de consulta agregamos una clase cliente a nuestro proyecto, en esa
misma clase seguiremos aumentando el cdigo referente a la creacin, actualizacin y
eliminacin de registros que hagamos con la entidad clientes.
Pgina 47
2008
Ejercicio 14
public void Guardar(string Codigo, string Nombre, string Direccion, string Telefono)
{
Cliente objCliente = new Cliente();
objCliente.CodCli = short.Parse(Codigo);
objCliente.NomCli = Nombre;
objCliente.DirCli = Direccion;
objCliente.TelCli = Telefono;
MiEsquema.Cliente.InsertOnSubmit(objCliente);
MiEsquema.SubmitChanges();
}
Cdigo: Instanciamos la clase cliente, luego asignamos a las propiedades los valores de los parmetros que
recibe el mtodo. Finalmente atravs de la instancia (MiEsquema) de nuestro ORM seleccionamos la entidad
que va a ser cambiada (Cliente) y llamamos al metodo InsertOnSubmit, le pasamos de parmetro nuestro
objeto cliente (objCliente) y el mtodo SubmitChanges() lo utilizaremos en las tres transacciones para
confirmar los cambios en la base de datos.
public void Modificar(string Codigo, string Nombre, string Direccion, string Telefono)
{
var objActualiza = (from cliente in MiEsquema.Cliente
where cliente.CodCli == short.Parse(Codigo)
select cliente).First();
objActualiza.NomCli = Nombre;
objActualiza.DirCli = Direccion;
objActualiza.TelCli = Telefono;
MiEsquema.SubmitChanges();
}
Cdigo: Hacemos una consulta LINQ que nos devuelva un registro de la entidad cliente. Para poder acceder
a las propiedades del objeto que cargamos notese que al final de la instruccin hemos utilizado el mtodo
First(); que indica que el resultado es solo un registro. A continuacin asignamos los nuevos valores y
enviamos a guardar atravs del mtodo SubmitChanges().
public void Eliminar(string Codigo)
{
var objElimina = (from cliente in MiEsquema.Cliente
where cliente.CodCli == short.Parse(Codigo)
select cliente).First();
MiEsquema.Cliente.DeleteOnSubmit(objElimina);
MiEsquema.SubmitChanges();
}
Cdigo: Igual que al momento de actualizar cargamos el registro que vamos a eliminar. Y ejecutamos la
accin a travs del mtodo DeleteOnSubmit pasando como parmetro objElimina. Y el mtodo
SubmitChanges() confirma los cambios en la BD.
Pgina 48
2008
{
objCliente.Eliminar(txtCodigo.Text);
Cargar();
}
#region CargarDatosCliente
private void Cargar()
{
dtgListado.DataSource=objCliente.ListadoCliente();
}
#endregion
Cdigo: En cada uno de los botones hacemos el llamado a los mtodos de la clase cliente y pasamos de
parmetros los valores de las cajas de texto. El mtodo cargar nos presentar los cambios que se van
realizando en la base de datos.
Antes de comenzar a escribir cdigo para utlizar procedimientos almacenados con LINQ,
debemos asegurarnos de que estos esten agregados en nuestro contexto. En caso de que
no hayamos agregado se lo puede hacer con tan solo arrastrar los PA a nuestro mapa
como se indic en el apartado MAPEO DE LA BASE DE DATOS.
Como LINQ, trata todas las entidades de la base de datos como clases del .NET o de
cualquier lenguaje orientado a objetos que implemente el Framework 3.0 que abarca a
LINQ, tambin deberemos realizar la instancia del contexto.
BDLINQDataContext MiEsquema = new BDLINQDataContext();
Investigadores: Tngl. Andrs Len O. - Ing. Jorge Ochoa
Pgina 49
2008
Cdigo: Para ejecutar procedimientos almacenados desde LINQ utilizamos la instancia de nuestro contexto
(MiEsquema), luego seleccionamos el procedimiento almacenado que se va a ejecutar (CliGuarda,
CliActualiza o CliElimina) y finalmente enviamos los parmetros ().
Para ejecutar los procedimientos almacenados desde LINQ, debemos utilizar la instancia
del contexto en nuestro caso lo llamamos MiEsquema, luego al poner (.) nos presenta los
objetos de nuestro ORM y nosotros deberemos seleccionar el nombre del PA que vamos a
ejecutar enviando entre parntesis los parmetros que este necesite.
Pgina 50
2008
Cargar();
}
private void btnModificar_Click(object sender, EventArgs e)
{
objCliente.ModificarPA(txtCodigo.Text,txtNombre.Text,txtDireccion.Text, txtTelefono.Text);
Cargar();
}
private void btnEliminar_Click(object sender, EventArgs e)
{
objCliente.EliminarPA(txtCodigo.Text);
Cargar();
}
#endregion
#region CargarDatosCliente
private void Cargar()
{
dtgListado.DataSource=objCliente.ListadoCliente();
}
#endregion
Cdigo: En el formulario se hace el mismo procedimiento que cuando hicimos las transacciones con
sentencias LINQ, solamente cambiando el nombre de los mtodos de la clase.
Pgina 51
2008
Una vez que hemos explicado como va a funcionar el programa es hora de comenzar a
escribir el cdigo. Vamos a agregar una clase factura (clsFactura) a nuestro proyecto que
acabamos de crear y escribiremos el siguiente cdigo:
BDLINQDataContext MiEsquema = new BDLINQDataContext();
DataTable dtDetalle;
public clsFactura() { }
Cdigo: Libreras utilizadas ,instancia del contexto, declaracin el DataTable que ser el detalle de la factura
y creacin del constructor por defecto de la clase factura.
Pgina 52
2008
dtDetalle.Columns["Total"].Expression=
"("+dtDetalle.Columns["Cantidad"]+")*("+dtDetalle.Columns["Precio"]+")";
return dtDetalle;
}
Cdigo: Genera el DataTable de la factura, instancia y agrega las columnas que va a tener, en el segundo
bloque definimos el tipo de dato que van a tener las columnas: precio, cantidad, total. El tercer bloque asigna
el valor por defecto de precio y cantidad. Terminamos asignando una expresin de clculo al DataTable con
el propsito que se calcule automticamente cada lnea de la factura.
Mensaje
private void Mensaje(string mensaje, string titulo)
{
MessageBox.Show(mensaje, titulo, MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
Cdigo: Este mtodo ser el encargado de presentar los mensajes de informacin de la clase factura
Nmero de Factura
public int pNumeroFactura
{
get
{
try
{
return (from numero in MiEsquema.FacturaCabecera
select numero.NumFac).Max() + 1;
}
catch {throw;}
}
}
Cdigo: Propiedad que devuelve el nmero de factura, La instruccin LINQ busca en la cabecera de factura el
mximo valor que tenga el campo NumFac y le suma 1.
Actualizar Detalle
public void ActualizarDetalle() { if (dtDetalle != null) { dtDetalle.AcceptChanges(); } }
Cdigo: Actualiza todos los cambios que se hayan hecho en el DataTable dtDetalle. Es como realizar una
confirmacin y aceptacin a las modificaciones realizadas en este.
Deshacer Cambios
public void DeshacerCambiosDetalle(){dtDetalle.RejectChanges();}
Cdigo: Deshace todos los cambios que se hayan realizado en el DataTable dtDetalle. Siempre y cuando no
se haya hecho antes un AcceptChanges.
Validar
private bool Validar(string CodCliente,string Nombre,string Direccion,string Fecha)
{
try
{
if (CodCliente.Trim() == "")
{
Mensaje("No ha ingresado un cdigo de cliente vlido", "Datos del cliente");
Investigadores: Tngl. Andrs Len O. - Ing. Jorge Ochoa
Pgina 53
2008
return false;
}
else if (Nombre.Trim() == "")
{
Mensaje("No ha ingresado el nombre del cliente", "Datos del cliente");
return false;
}
else if (Direccion.Trim() == "")
{
Mensaje("No ha ingresado la direccin del cliente", "Datos del cliente");
return false;
}
else if (Nombre.Trim() == "")
{
Mensaje("No ha indicado la fecha de facturacin", "Fecha Factura");
return false;
}
else if (dtDetalle.Rows.Count == 0)
{
Mensaje("Debe ingresar al menos un item paa facturar", "Facturar en cero");
return false;
}
return true;
}
catch
{
throw;
}
}
Cdigo: Mtodo de validacin que devuelve verdadero si todos los datos estn correctos, caso contrario a
travs del mtodo mensaje informa al usuario que campos le falta llenar.
Guardar Factura
public void Guardar(string CodCliente, string NomCliente, string Direccion, string telefono,
string Fecha, string total)
{
try
{
ActualizarDetalle();
int numero = pNumeroFactura;
if (Validar(CodCliente, NomCliente, Direccion, Fecha))
{
MiEsquema.FacCabGuarda(numero,short.Parse(CodCliente),
DateTime.Parse(Fecha),decimal.Parse(total));
for (int i = 0; i < dtDetalle.Rows.Count; i++)
{
MiEsquema.FacDetGuarda(numero,
short.Parse(dtDetalle.Rows[i][0].ToString().Trim()),
int.Parse(dtDetalle.Rows[i][2].ToString().Trim()),
decimal.Parse(dtDetalle.Rows[i][3].ToString().Trim()),
decimal.Parse(dtDetalle.Rows[i][4].ToString().Trim()));
}
if (MessageBox.Show("Desea generar el archivo XML de esta factura", "XML",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
SaveFileDialog sfdArchivo = new SaveFileDialog();
bool Preguntar = true;
while (Preguntar == true)
{
Investigadores: Tngl. Andrs Len O. - Ing. Jorge Ochoa
Pgina 54
2008
sfdArchivo.ShowDialog();
if (sfdArchivo.FileName.Trim() == "")
{
if (MessageBox.Show("Debe indicar una ruta para generar el archvivo. Desea
volver a intentar", "Ruta archivo XML", MessageBoxButtons.YesNo,
MessageBoxIcon.Question) == DialogResult.No)
{
Preguntar = false;
}
}
else
{
Preguntar = false;
}
}
GenerarXML(numero, CodCliente, NomCliente, Direccion, telefono, total,
sfdArchivo.FileName);
}
}
catch (Exception ex)
{
Mensaje(ex.Message, "Guardar");
}
}
Pgina 55
2008
Cdigo: Crea el archvio XML de la factura que se guard. Comienza haciendo una validacin que el
parmetro ruta no est en blanco. Esto porque en el bucle que hay en el mtodo que guarda la factura, s
se da la opcin al usuario de que no seleccione ningn lugar para guardar. En este caso no se genera el
archivo XML. Si pasa esta condicin empieza a realizar los giguientes pasos:
1.- Declara un XElement Factura y dentro de esta instancia crea el nodo cabecera.
2.- En la misma instancia del nodo cabecera, crea los nodos hijos que tendrn la informacin de la
cabecera de la factura. Estos elementos son:
- Nmero de factura
- Cdigo del cliente.
- Nombre del cliente.
- Direccin del cliente.
- Telfono del cliente.
3.- Creamos un nodo detalle que contendr todos los productos vendidos.
4.- Dentro del nodo detalle creamos elementos que contengan los valores:
- Item que es el nmero de lnea del detalle
- Codido del producto
- Descripcin del producto
- Cantidad vendida
- Precio de venta
- Total de lnea
5.- Agregamos todos los subnodos al nodo item.
6.- Creamos el elemento Total y asignamos el valor de la venta.
7.- Agregamos el nodo item al nodo detalle.
8.- Agregamos el nodo detalle al nodo factura.
9.- Agregamos el nodo total a la factura.
10.- Guardamos el archivo xml en la ruta especificada por el usuario.
Pgina 56
2008
Cdigo: Creamos dos mtodos. El primero que calcular el total de la venta y el segundo que habilitar e
inhabilitar los controles de acuerdo al parmetro que reciba.
BOTONES
private void btnBuscarCliente_Click(object sender, EventArgs e)
{
frmBuscarCliente objBuscar = new frmBuscarCliente();
objBuscar.ShowDialog();
object[] valor = objBuscar.pCliente;
if (valor != null)
{
txtCodCliente.Text = valor[0].ToString();
txtNombre.Text = valor[1].ToString();
txtDireccion.Text = valor[2].ToString();
txtTelefono.Text = valor[3].ToString();
}
}
private void btnAgregarProductos_Click(object sender, EventArgs e)
{
frmProductos objProducto = new frmProductos((DataTable)dtgDetalle.DataSource);
objProducto.ShowDialog();
total();
}
private void btnCrearCliente_Click(object sender, EventArgs e)
{
Clientes.frmCliente objCliente = new pruebaLINQ.Clientes.frmCliente();
objCliente.ShowDialog();
}
Cdigo: En los tres botones del formulario escribimos el Cdigo correspondiente a cada uno de ellos.
Acurdese el botn buscar cliente est representado por , lo que hacemos en cada uno de los botones es
llamar al respectivo formulario.
1.- Botn Buscar Cliente.- Llamamos al formulario de buscar clientes que nos devolver un vector
con toda la informacin del cliente que seleccionemos. Como se ver al momento que construyamos
dicho formulario.
2.- Botn Agregar Productos.- Llama al formulario que agrega los productos. Este formulario recibe
de parmetro un DataTable que ser el que almacene los items. Despus de cargar cada item llama
al mtodo que calcula el Total().
3.- Llama al formulario que crea, modifica y elimina los clientes.
Pgina 57
2008
EVENTOS
private void txtTelefono_KeyPress(object sender, KeyPressEventArgs e)
{
if (!Char.IsDigit(e.KeyChar) && e.KeyChar != 13 && e.KeyChar != 8)
{
e.Handled = true;
}
}
private void dtgDetalle_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
MessageBox.Show("Los valores ingresados en el detalle no son correctos", "Detalle
Factura");
}
private void dtgDetalle_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0)
{
frmProductos objProducto = new frmProductos();
if (e.ColumnIndex == 2)
{
if (int.Parse(dtgDetalle.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString()) <=
objProducto.Disponible(dtgDetalle.Rows[e.RowIndex].Cells[0].Value))
{
total();
}
else
{
objFactura.DeshacerCambiosDetalle(); MessageBox.Show("No dispone de la cantidad
solicitada", "Existencias", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}
}
Esto se debe a que al crear el DataTable nosotros asignamos el tipo de datos entero.
Investigadores: Tngl. Andrs Len O. - Ing. Jorge Ochoa
Pgina 58
2008
Pgina 59
2008
Cdigo: Las primeras lneas declaran las instancias del DataTable y del contexto. Despus podemos ver que
tenemos dos constructores el uno sin parmetros que controla la existencia de productos cuando se lo llama
desde la factura en el evento CellValueChanged y el otro que recibe de parmetro un DataTable que se utiliza
cuando se est agregando productos. Ver botn Productos en el formulario de Factura.
LOAD
private void frmProductos_Load(object sender, EventArgs e)
{
dtgProductos.DataSource = from prd in MiEsquema.Producto
where prd.EstPrd == true
orderby prd.CodPrd
select new
{ Codigo = prd.CodPrd,
Descripcion = prd.DesPrd,
Precio = prd.PrePrd,
Existencia=prd.ExiPrd
};
dtgFacturados.DataSource = dtFacturado;
}
Cdigo: En el Load() del formulario, escribimos la instruccin LINQ que cargue los registros de la entidad
producto en los cuales el estado del producto sea activo y ordenado por cdigo. En el select podemos
observar que cada campo de la entidad producto esta precedido por un identificador y el signo igual. Esto es
el equivalente a la palabra clave AS de las sentencias SQL.
METODOS
private bool VerificarExistencia(object Codigo)
{
for (int i = 0; i < dtFacturado.Rows.Count; i++)
{
if (dtFacturado.Rows[i][0].ToString().Trim() == Codigo.ToString().Trim())
{
if (Disponible(Codigo) > (int.Parse(dtFacturado.Rows[i][2].ToString())))
{
dtFacturado.Rows[i][2] = int.Parse(dtFacturado.Rows[i][2].ToString()) + 1;
}
else
{
MessageBox.Show("No dispone de la cantidad solicitada", "Existencia",
MessageBoxpButtons.OK, MessageBoxIcon.Warning);
}
return true;
}
}
return false;
}
public int Disponible(object codigo)
{
return int.Parse(((from exis in MiEsquema.Producto
where exis.CodPrd.Trim() == codigo.ToString().Trim()
select exis.ExiPrd).Single()).ToString());
}
Pgina 60
2008
Cdigo: Este es el nico evento que tiene el formulario de agregar productos. Cuando hace click en la
cabecera de las filas. Agrega una fila al DataTable que pasamos de parmetro y se reflejan los cambios en el
detalle de la factura inmediatamente.
Pgina 61
2008
En la figura anterior podemos notar que hay una pantalla encerrada. Esa es la que nos
permitir buscar a nuestros clientes. El cdigo es el siguiente
BDLINQDataContext MiEsquema = new BDLINQDataContext();
object[] cliente = null;
Cdigo: De igual forma que en las ventanas anteriores, debemos instanciar nuestro contexto. Tambin
tenemos un vector object que nos devolver el cliente seleccionado.
LOAD
private void frmBuscarCliente_Load(object sender, EventArgs e)
{
dtgCliente.DataSource = from cli in MiEsquema.Cliente
where cli.EstCli == true
select new { cli.CodCli, cli.NomCli, cli.DirCli, cli.TelCli };
}
Cdigo: Instruccin LINQ que carga todos los clientes que estn activos y el resultado se asigna a una grilla.
EVENTOS
private void dtgCliente_RowHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
pCliente= new object[] {dtgCliente.Rows[e.RowIndex].Cells[0].Value,
dtgCliente.Rows[e.RowIndex].Cells[1].Value,
dtgCliente.Rows[e.RowIndex].Cells[2].Value,
dtgCliente.Rows[e.RowIndex].Cells[3].Value,
};
this.Close();
}
Pgina 62
2008
Cdigo: Toma la fila seleccionada y la asigna al vector que declaramos en la parte superior.
PROPIEDADES
public object[] pCliente
{
set {cliente = value; }
get { return cliente; }
}
Para terminar haremos la implementacin del formulario crear cliente. Que ser llamado
desde el botn cliente. El formulario para realizar transacciones con clientes ha sdido
implementado basndonos en el formulario de los ejemplos de LINQ a SQL, dejando solo
los mtodos que ejecutan los procedimientos almacenados.
Pgina 63
2008
Cdigo: Cada mtodo llama al respectivo procedimiento almacenado, salvo el mtodo de ListadoCliente()
que ejecuta la consulta LINQ que nos devolver todos los registros de clientes.
Pgina 64
2008
Crear las tablas necesarias en la base de datos y una pantalla que registre los
ingresos de productos. La respuesta se guardar en la tabla respectiva y generar
un archivo XML con la informacin del ingreso.
Construir las tablas necesarias en la base de datos y una ventana que permita
registrar una devolucin de factura. Generar el archivo XML correspondiente.
Pgina 65
2008
CONCLUSIONES
LINQ, es una utilidad que inicialmente ha sido implementada en el framework 3.0 para los
lenguajes de c# 3.0 y Visual Basic 9.0 pero que por la funcionalidad y versatilidad que
ofrece para la conexin con diferentes orgenes de datos. En poco tiempo se ir
incorporando a los dems lenguajes para que pueda ser usado por los desarrolladores de
todos los compiladores.
Tambin podemos decir que los desarrolladores que se dediquen a estudiar y aplicar esta
tecnologa unicamente necesitarn conocer dos lenguajes para acceder a cualquier fuente
de datos. LINQ como el lenguaje principal y SQL que se convertir en una herramienta
secundarias para la administracin de la base de datos y esencialemnte para la creacin
de procedimientos almacenados que como se explico en el apartado LLAMADO A
PROCEDIMIENTOS ALMACENADOS el lenguaje integrado de consultas mejora la
potencialidad de estos y no los reemplaza.
Para concluir acotamos que en la actualidad con la demanda que tienen las aplicaciones
web, formatos XML, etc. Se necesita que los desarrolladores de software sean cada vez
ms eficientes y esta tecnologa es una de las utensilios que nos facilitarn cumplir con
esta meta.
Pgina 66
2008
RECOMENDACIONES
Las consultas embebidas en los lenguajes de programacin son muy extensas por lo que
para realizar un estudio a fondo que nos permita explotar todo el potencial que estas nos
ofrecen necesitaramos dedicar por lo menos un ao a la investigacin de esta
metodologa en todas sus funcionalidades.
En esta monografa hemos realizado una introduccin a las prerrogativas bsicas que nos
brinda LINQ en las reas de LINQ a SQL y LINQ a XML. Pero le recordamos a nuestros
lectores que el Lenguaje Integrado de Consultas permite conectarse a cualquier origen de
datos que herede de IEnumerable.
Pgina 67
2008
BIBLIOGRAFIA
www.msdn.com.es
www.thingking.net
www.elguille.com
www.developer.mozilla.org
www.wikipedia.org
http://geeks.ms
www.netdeveloper.com
www.onglases.net
www.wikipedia.org
Pgina 68