Consultas básicas con filtro y Orden
Las consultas básicas usando las clases LINQ to SQL son muy limpias y legibles. Además, las clases LINQ to SQL recuperan sólo los datos que solicitamos.
El siguiente código de ejemplo lista los clientes que contengan la palabra "restaurante" en el nombre de la empresa, ordenados en el código postal:
-----------------------------------VB------------------------------------
Dim ctx = New NorthwindDataContext() Dim sw = New StringWriter() ctx.Log = sw Dim customers = From c In ctx.Customers _ Where c.CompanyName.Contains("Restaurant")Order By c.PostalCodec dg.ItemsSource = customers MessageBox.Show(sw.GetStringBuilder().ToString())
-----------------------------------CS------------------------------------
var ctx = new NorthwindDataContext(); var sw = new StringWriter(); ctx.Log = sw; var customers = from c in ctx.Customers where c.CompanyName.Contains("Restaurant") orderby c.PostalCode select c; dg.ItemsSource = customers; MessageBox.Show(sw.GetStringBuilder().ToString());la consulta genera el siguiente sql:
SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle],
[t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0]. [Phone], [t0].[Fax] FROM [dbo].[Customers] AS [t0] WHERE [t0].[CompanyName] LIKE @p0 ORDER BY [t0].[PostalCode] -- @p0: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [%Restaurant%]
Proyecciones
Uno de los problemas de la consulta anterior es que se devuelven todas las columnas de la tabla Customer, pero podría necesitarse sólo CustomerID, CompanyName y PostalCode. Se puede utilizar una proyección para limitar los valores de columna devueltos desde SQL Server:
-----------------------------------VB------------------------------------
Dim ctx = New NorthwindDataContext() Dim sw = New StringWriter() ctx.Log = sw Dim customers = From c In ctx.Customers Where c.CompanyName.Contains("Restaurant") Order By c.PostalCode Select New With {c.CustomerID, c.CompanyName, c.PostalCode} dg.ItemsSource = customers MessageBox.Show(sw.GetStringBuilder().ToString())
-----------------------------------CS------------------------------------
var ctx = new NorthwindDataContext(); var sw = new StringWriter(); ctx.Log = sw; var customers = from c in ctx.Customers where c.CompanyName.Contains("Restaurant") orderby c.PostalCode select new { c.CustomerID, c.CompanyName, c.PostalCode }; dg.ItemsSource = customers; MessageBox.Show(sw.GetStringBuilder().ToString());
Inner joins
Una combinación interna produce la salida sólo cuando las dos tablas que se unencoinciden en la clave única para extranjeros key.The siguiente consulta LINQ produce un inner join de la tabla Customers a la tabla Orders y recupera CustomerID CompanyName,OrderID y OrderDate.
-----------------------------------VB------------------------------------
Dim ctx = New NorthwindDataContext() Dim sw = New StringWriter() ctx.Log = sw Dim customers = ctx.Customers.Join(ctx.Orders, Function(c) c.CustomerID, Function(o) o.CustomerID, Function(c, o) New With { c.CustomerID, c.CompanyName, o.OrderID, o.OrderDate }) _ .OrderBy(Function(r) r.CustomerID) _ .ThenBy(Function(r) r.OrderID) dg.ItemsSource = customers MessageBox.Show(sw.GetStringBuilder().ToString())
-----------------------------------CS------------------------------------
var ctx = new NorthwindDataContext(); var sw = new StringWriter(); ctx.Log = sw; var customers = ctx.Customers.Join( ctx.Orders, c => c.CustomerID, o => o.CustomerID, (c, o) => new { c.CustomerID, c.CompanyName, o.OrderID, o.OrderDate }) .OrderBy(r=>r.CustomerID) .ThenBy((r=>r.OrderID)); dg.ItemsSource = customers; MessageBox.Show(sw.GetStringBuilder().ToString());
y usando linQ:
-----------------------------------VB------------------------------------
Dim ctx = New NorthwindDataContext() Dim sw = New StringWriter() ctx.Log = sw Dim customers = From c In ctx.Customers Join o In ctx.Orders On c.CustomerID Equals o.CustomerID Order By c.CustomerID, o.OrderID Select New With { c.CustomerID, c.CompanyName, o.OrderID, o.OrderDate } dg.ItemsSource = customers MessageBox.Show(sw.GetStringBuilder().ToString())
-----------------------------------CS------------------------------------
var ctx = new NorthwindDataContext(); var sw = new StringWriter(); ctx.Log = sw; var customers = from c in ctx.Customers join o in ctx.Orders on c.CustomerID equals o.CustomerID orderby c.CustomerID, o.OrderID select new { c.CustomerID, c.CompanyName, o.OrderID, o.OrderDate }; dg.ItemsSource = customers; MessageBox.Show(sw.GetStringBuilder().ToString());
se genera el siguiente sql:
SELECT [t0].[CustomerID], [t0].[CompanyName], [t1].[OrderID], [t1].[OrderDate] FROM [dbo].[Customers] AS [t0] INNER JOIN [dbo].[Orders] AS [t1] ON [t0].[CustomerID] = [t1].[CustomerID] ORDER BY [t0].[CustomerID], [t1].[OrderID]
Outer Joins
Un outer join produce una salida, incluso si el elemento de la tabla externa no coincide con la tabla interna. Para realizar una outer join, se debe indicar que aún desea la fila de la tabla externa, incluso si no hay ninguna coincidencia con la tabla interna.Se pueden realizar combinaciones externas mediante el método de extensión GroupJoin:
-----------------------------------VB------------------------------------
Dim ctx = New NorthwindDataContext() Dim sw = New StringWriter() ctx.Log = sw Dim customers = ctx.Customers.GroupJoin(ctx.Orders, _ Function(c) c.CustomerID, _ Function(o) o.CustomerID, _ Function(c, o) New With { c.CustomerID, c.CompanyName, .Orders = o }) _ .SelectMany(Function(t) t.Orders.DefaultIfEmpty().Select( _ Function(ord) New With { t.CompanyName, t.CustomerID, .OrderID = CType(ord.OrderID, Nullable(Of Integer)), .OrderDate = CType(ord.OrderDate, Nullable(Of DateTime)) })) _ .OrderBy(Function(r) r.CustomerID) _ .ThenBy(Function(r) r.OrderID) dg.ItemsSource = customers MessageBox.Show(sw.GetStringBuilder().ToString())
-----------------------------------CS------------------------------------
var ctx = new NorthwindDataContext(); var sw = new StringWriter(); ctx.Log = sw; var customers = ctx.Customers.GroupJoin( ctx.Orders, c => c.CustomerID, o => o.CustomerID, (c, o) => new { c.CustomerID, c.CompanyName, Orders = o }) .SelectMany(t=>t.Orders.DefaultIfEmpty().Select(ord=> new { t.CompanyName, t.CustomerID, OrderID=(int?)ord.OrderID, OrderDate=(DateTime?) ord.OrderDate})) .OrderBy(r => r.CustomerID).ThenBy((r => r.OrderID)); dg.ItemsSource = customers; MessageBox.Show(sw.GetStringBuilder().ToString());
También se puede realizar un outer join mediante una consulta LINQ con la palabra clave join:
-----------------------------------VB------------------------------------
Dim ctx = New NorthwindDataContext() Dim sw = New StringWriter() ctx.Log = sw Dim customers = From c In ctx.Customers Group Join o In ctx.Orders On c.CustomerID Equals o.CustomerID Into InJoin = Group From outJoin In InJoin.DefaultIfEmpty() Order By c.CustomerID, outJoin.OrderID Select New With { c.CustomerID, c.CompanyName, .OrderID = CType(outJoin.OrderID, Nullable(Of Integer)), .OrderDate = CType(outJoin.OrderDate, Nullable(Of DateTime)) } dg.ItemsSource = customers MessageBox.Show(sw.GetStringBuilder().ToString())
-----------------------------------CS------------------------------------
var ctx = new NorthwindDataContext(); var sw = new StringWriter(); ctx.Log = sw; var customers = from c in ctx.Customers join o in ctx.Orders on c.CustomerID equals o.CustomerID into inJoin from outJoin in inJoin.DefaultIfEmpty() orderby c.CustomerID, outJoin.OrderID select new { c.CustomerID, c.CompanyName, OrderID = (int?)outJoin.OrderID, OrderDate = (DateTime?)outJoin.OrderDate };w dg.ItemsSource = customers; MessageBox.Show(sw.GetStringBuilder().ToString());
El SQL obtenido:
SELECT [t0].[CustomerID], [t0].[CompanyName], [t1].[OrderID] AS [OrderID2], [t1].[OrderDate] AS [OrderDate] FROM [dbo].[Customers] AS [t0] LEFT OUTER JOIN [dbo].[Orders] AS [t1] ON [t0].[CustomerID] = [t1].[CustomerID] ORDER BY [t0].[CustomerID], [t1].[OrderID]
Agrupación y agregación
LINQ to SQL también permite realizar operaciones de agrupación para recuperar los resultados agregados, por ej:
Dim ctx = New NorthwindDataContext() Dim sw = New StringWriter() ctx.Log = sw Dim orders = From o In ctx.Order_Details Group o By OrderID = o.OrderID Into grouped = Group Select New With { .OrderID = OrderID, .Total = grouped.Sum(Function(line) _ line.Quantity * line.UnitPrice * _ (1 - CType(line.Discount, Decimal))) } dg.ItemsSource = orders MessageBox.Show(sw.GetStringBuilder().ToString())
-----------------------------------CS------------------------------------
var ctx = new NorthwindDataContext(); var sw = new StringWriter(); ctx.Log = sw; var orders = from o in ctx.Order_Details group o by o.OrderID into grouped select new { OrderID = grouped.Key, Total = grouped.Sum( line=>line.Quantity * line.UnitPrice * (1 - (decimal)line.Discount)) };
Este ejemplo de código agrupa las filas Order_Details por OrderID y despues se calcula el total de cada pedido mediante el cálculo de la suma de las partidas de la orden. Para calcular la suma, cada línea tenía que ser calculado multiplicando la cantidad por el precio unitario por uno menos el descuento.
Y el SQL resultante seria:
SELECT SUM([t1].[value]) AS [Total], [t1].[OrderID] FROM ( SELECT (CONVERT(Decimal(29,4),[t0].[Quantity])) * [t0].[UnitPrice] * (@p0 - (CONVERT(Decimal(33,4),[t0].[Discount]))) AS [value], [t0].[OrderID] FROM [dbo].[Order Details] AS [t0] ) AS [t1] GROUP BY [t1].[OrderID] -- @p0: Input Decimal (Size = -1; Prec = 33; Scale = 4) [1]
Resumen de la lección
■ Se pueden utilizar las propiedades de tabla en el DataContext para ejecutar consultas LINQ.
■ Si se proporciona una cláusula where , LINQ to SQL creará una consulta SQL que incluye la cláusula WHERE para limitar las filas devueltas a la aplicación.
■ Si se proporciona una proyección en la cláusula SELECT para limitar las propiedades que se seleccionan, LINQ to SQL creará una consulta SQL que incluye un filtro de columna coincidente para limitar los datos devueltos a la aplicación.
No hay comentarios:
Publicar un comentario