linq to sql - tipos - C#LINQ equivalente a una consulta SQL algo compleja
solo se admiten tipos primitivos o tipos de enumeraciĆ³n en este contexto (2)
Entonces tengo una consulta SQL como sigue
SELECT P.Date, P.CategoryName, P.ProductName, SUM(Quantity) Quantity, SUM(Sales) TotalSales, IsLevelThree
FROM Products P LEFT JOIN LevelThreeTracking LTT
ON P.Date = LTT.Date AND P.CategoryName = P.CategoryName AND P.SecurityID = LTT.SecurityID
WHERE P.Date = ''12-31-2007'' AND P.CategoryName= ''CategoryName''
GROUP BY P.Date, P.CategoryName, P.ProductName, LTT.IsLevelThree
HAVING SUM(Quantity) <> 0
ORDER BY P.ProductName
Estoy tratando de convertirlo a la sintaxis de C # LINQ y tengo la configuración de DataContext con las 2 tablas. Lo intenté un par de veces (última revisión a continuación) pero el sql que se genera parece monstruosamente complejo y se agota. dtpBeginning es un DateTimePicker.
var results = from p in dbFAS.Products
group p by new {p.Date, p.CategoryName, p.ProductName}
into gp
join ltt in dbFAS.LevelThreeTracking on
new {gp.Key.Date, gp.Key.CategoryName, gp.Key.ProductName} equals
new {ltt.Date, ltt.CategoryName, ltt.ProductName} into everything
from e in everything.DefaultIfEmpty()
where gp.Key.Date == dtpBeginning.Value.Date && gp.Key.CategoryName == "CategoryName" && gp.Sum(p=>p.Quantity) != 0
select new
{
gp.Key.Date,
gp.Key.CategoryName,
gp.Key.ProductName,
Quantity = gp.Sum(hp=>hp.Quantity),
TotalSales = gp.Sum(hp=>hp.Sales),
e.Level3
};
¿Hay algo simple que me estoy perdiendo? ¿Alguna idea sobre cómo refactorizar la declaración LINQ para obtener algo mejor?
¿Realmente se debe convertir a LINQ? Sugeriría que coloques esa consulta en un procedimiento almacenado porque la consulta LINQ equivalente es dolorosamente ilegible y no se puede mantener.
Prueba esta consulta y avísame si funciona. Cambié el join en una cláusula where, esto debería eliminar todas las subconsultas complejas que LINQ genera al traducir a SQL.
No estoy seguro de si obtuve la parte LEFT OUTER JOIN correcta. Acabo de incluir una condición OR que prueba si existe un lado.
from p in dbFAS.Products
from ltt in dbFAS.LevelThreeTracking
where p.CategoryName == "CategoryName"
&& (p.Date == ltt.Date || p.Date)
&& (p.CategoryName == ltt.CategoryName || p.CategoryName)
&& (p.ProductName == ltt.ProductName || p.ProductName)
&& p.Quantity > 0
group p by new {p.Date, p.CategoryName, p.ProductName, p.Quantity, p.Sales, ltt.Level3}
into gp
select new
{
gp.Key.Date,
gp.Key.CategoryName,
gp.Key.ProductName,
Quantity = gp.Sum(hp=>hp.Quantity),
TotalSales = gp.Sum(hp=>hp.Sales),
ltt.Level3
};
EDIT: lo pensé un poco más, y esto podría ser un poco más claro e incluso podría compilar! (El último no lo hará debido a las cláusulas ||
from gp in
(from p in dbFAS.Products
join ltt in dbFAS.LevelThreeTracking on
new {p.Date, p.CategoryName, p.ProductName}
equals new {ltt.Date, ltt.CategoryName, ltt.ProductName}
into temp
where p.CategoryName == "CategoryName"
&& p.Quantity > 0
from t in temp.DefaultIfEmpty()
select new
{
p.Date,
p.CategoryName,
p.ProductName,
p.Quantity,
p.Sales,
t.Level3
})
group gp by new {gp.Date, gp.CategoryName, gp.ProductName, gp.Level3}
select new
{
gp.Key.Date,
gp.Key.CategoryName,
gp.Key.ProductName,
Quantity = gp.Sum(hp=>hp.Quantity),
TotalSales = gp.Sum(hp=>hp.Sales),
gp.Level3
}