I have a LINQ query that is returning the results and format I desire, but it seems a bit slow. Wondering if there is a way to improve its performance? The Items and Skus records are 1:1. For each Item there 5 ItemWhse and 5 SkuWhse records for each Skus record.
var orderItems = from item in db.Items
join sku in db.Skus
on item.Sku equals sku.Sku
where item.OrderNumber == 12345678
select new
{
Item = item,
ItemWhse = from itemWhse in db.ItemWarehouse
where itemWhse.OrderNumber == item.OrderNumber
&& itemWhse.LineNumber == item.LineNumber
select itemWhse,
Sku = sku,
SkuWhse = from skuWhse in db.SkuWarehouse
where skuWhse.Sku == sku.Sku
select skuWhse
};
It might be slow because you are using subqueries. Try this out:
var orderItems = from item in db.Items
join sku in db.Skus
on item.Sku equals sku.Sku
join itemWhse in db.ItemWarehouse
on new { item.OrderNumber, item.LineNumber } equals new { itemWhse.OrderNumber, itemWhse.LineNumber }
join skuWhse in db.SkuWarehouse
on item.Sku equals skuWhse.Sku
where item.OrderNumber == 12345678
select new
{
Item = item,
ItemWhse = itemWhse,
Sku = sku,
SkuWhse = skuWhse
};
Related
I am trying to get data from 2 tables using a left join to a nested query. This allows me to get data from Item table but not the cart(nested query) table:
var q = from s in db.Items
join sub in (from c in db.Carts
where c.CartID == 1
group c by c.ItemID into g
select new
{
ItemID = g.Key,
Qty = g.Select(s => s.Qty)
}) on s.ItemID equals sub.ItemID into a
select new ItemViewModel
{
CategoryID = s.CategoryID,
Description = s.Description,
Price = s.Price,
**This being the issue------>>>>>>>** //Qty = a.Select(j => j.Qty),
ItemID = s.ItemID,
ItemName = s.ItemName
};
viewModel = q.ToList();
The query i am trying to acheive is:
select Items.*, Cart.Qty
from Items
left join (select ItemID, Qty from carts where CartID = 1 ) Cart
on Items.ItemID = Cart.ItemID
You can use GroupJoin with SelectMany for LEFT JOIN SQL Query and get the desired output.
var result = db.Items.GroupJoin(db.Carts.Where(x => x.CartID == 1), item => item.ItemID, cart => cart.ItemID,
(item, cart) => new { item, cart })
.SelectMany(x => x.cart.DefaultIfEmpty(), (it, ca) =>
{
return new ItemViewModel
{
ItemName = it.item.ItemName,
Price = it.item.Price,
ItemID = it.item.ItemID,
// ... .... ....
// Fill the required columns from it.Item property..
Qty = ca != null ? ca.Qty : 0
};
}).ToList();
EDIT: The LINQ version with SelectMany.
var result = from s in db.Items
join sub in (from c in db.Carts
where c.CartID == 1
select c)
on s.ItemID equals sub.ItemID into joined
from row in joined.DefaultIfEmpty()
select new ItemViewModel
{
CategoryID = s.CategoryID,
Description = s.Description,
Price = s.Price,
Qty = row != null ? row.Qty : 0,
ItemID = s.ItemID,
ItemName = s.ItemName
};
The C# Fiddle with sample data.
If I'm understanding correctly, and assuming that ItemViewModel.Qty property is just an int, the simplest form of the query you want is:
var q = from item in items
join cart in
(from cart in carts where cart.CartID == 1 select cart)
on item.ItemID equals cart.ItemID into itemCarts
select new ItemViewModel
{
ItemID = item.ItemID,
Qty = itemCarts.Sum(cart => cart.Qty)
};
If you want to only slightly modify/fix your query:
var q = from s in db.Items
join sub in (from c in db.Carts
where c.CartID == 1
group c by c.ItemID into g
select new
{
ItemID = g.Key,
Qty = g.Sum(s => s.Qty)
// or Qty = g.Select(s => s.Qty)
// and below: Qty = a.SelectMany(x => x.Qty).Sum()
})
on s.ItemID equals sub.ItemID into a
select new ItemViewModel
{
CategoryID = s.CategoryID,
Description = s.Description,
Price = s.Price,
Qty = a.Sum(x => x.Qty),
ItemID = s.ItemID,
ItemName = s.ItemName
};
I'm trying to join two group by queries to get one results set.
var query = from PP in _db.paymentPlans
join APP in _db.Applications on PP.applicationID equals APP.ApplicationId
join C in _db.Courses on APP.courseID equals C.courseID
where PP.active == true && APP.agentID == agentID
orderby C.courseID ascending
group new {C,PP} by new {C.courseID} into totalRecievable
// Query 1
from PD in _db.paymentDetails
join PP in _db.paymentPlans on PD.paymentPlanID equals PP.paymentPlanID
join APP in _db.Applications on PP.applicationID equals APP.ApplicationId
join C in _db.Courses on APP.courseID equals C.courseID
where PP.active == true && APP.agentID == agentID
orderby C.courseID ascending
group new { C,PD } by new { C.courseID, C.cricosCode, C.courseName } into paymentsCourseWise
// Query 2
select new PdPpAppCourseModel
{
courseID = paymentsCourseWise.Key.courseID,
cricosCode = paymentsCourseWise.Key.cricosCode,
courseName = paymentsCourseWise.Key.courseName,
totalAmount = totalRecievable.Sum(x => x.PP.totalAmount),
paidAmount = paymentsCourseWise.Sum(x => x.PD.paidAmount)
}).ToList();
Total about is taken from query 1 as it should group in payment plan(PP) level.
You can only combine enumerations of the same type, you could project both to a common class and then concatenate them:
var result1 = db1.table.Where(a=>a.value>0).Select( x=> new Foo() { //set props });
var result2 = db2.table.Where(a=>a.value>0).Select( x=> new Foo() { //set props });
var resultSum = result1.Concat(result2);
Similarly you can apply this in your code and join this two groups.
I have three levels of master detail relation, One purchase can contain multiple challan, one challan can contain multiple items. each item has some quantity. I need to calculate total item quantity for every purchase. I've done that by the following, but it takes a lot of time just for a handful of data. I'm worried what will happen when the amount of data becomes large. Is there a way to do this in a single query using join or anything else? Thanks in advance.
var allData = (from p in _context.Prq_Purchase.AsEnumerable()
//where p.RecordStatus == "NCF"
from s in _context.Sys_Supplier
where s.SupplierID == p.SupplierID
from sa in _context.Sys_SupplierAddress
where sa.SupplierAddressID == p.SupplierAddressID
orderby p.PurchaseID descending
select new PurchaseReceive
{
PurchaseID = (p.PurchaseID).ToString(),
PurchaseNo= p.PurchaseNo,
SupplierID = (p.SupplierID).ToString(),
SupplierName = s.SupplierName,
Address = sa.Address,
SupplierAddressID = (p.SupplierAddressID).ToString(),
PurchaseCategory = p.PurchaseCategory,
PurchaseType = p.PurchaseType,
PurchaseYear = p.PurchaseYear,
PurchaseDate = (p.PurchaseDate).ToString("dd'/'MM'/'yyyy"),
RecordStatus= DalCommon.ReturnRecordStatus(p.RecordStatus)
}).ToList();
foreach(var Purchase in allData)
{
decimal TotalQty = 0;
var ChallanList= (from c in _context.Prq_PurchaseChallan.AsEnumerable()
where (c.PurchaseID).ToString()==Purchase.PurchaseID
select c).ToList();
foreach(var Challan in ChallanList)
{
var ItemList = (from i in _context.Prq_PurchaseChallanItem.AsEnumerable()
where i.ChallanID == Challan.ChallanID
select i).ToList();
foreach(var Item in ItemList )
{
TotalQty = TotalQty + Item.ReceiveQty;
}
}
Purchase.TotalItem = TotalQty;
}
Can you please help to convert this from sql to linq, i am new to linq and been trying this and couldn't succeed. Let me know if this is even possible or not?
SELECT max(Products.ProductID) as ProductID, Products.SKU, Products.Name, Products.RRP, Products.Price,
max(Products.FrontTall) as FrontTall,
ProductsCategory.SortOrder,
Products.ColorValue,
max(Products.ColorImg) as ColorImg,
Products.IsPrimary,
Products.Visible
FROM Products INNER JOIN ProductsCategory ON Products.ProductID = ProductsCategory.ProductID
WHERE (ProductsCategory.CategoryID = 5 ) AND (Products.Visible = 1) AND (Products.Inactive = 0) AND (Products.Deleted = 0 or Products.Deleted is null)
GROUP BY SKU, Products.Name, RRP, Price, ColorValue, ProductsCategory.SortOrder, IsPrimary, Visible
AND this is what i am trying
var products = (from p in db.Products
join cp in db.ProductsCategories on p.ProductID equals cp.ProductID
where cp.CategoryID == catId && p.Visible == true && p.Inactive == false && (p.Deleted == null || p.Deleted == false)
group p by new {
p.SKU,
p.Name,
p.RRP,
p.Price,
p.ColorValue,
p.IsPrimary,
p.Visible,
cp.SortOrder
} into grouped
select new {
ProductID,
FrontTall,
ColorImg,
SKU = grouped.Key.SKU,
Name = grouped.Key.Name,
RRP = grouped.Key.RRP,
Price = grouped.Key.Price,
ColorValue = grouped.Key.ColorValue,
IsPrimary = grouped.Key.IsPrimary,
Visible = grouped.Key.Visible,
SortOrder = grouped.Key.SortOrder
})
.OrderBy(x => x.SortOrder);
I need to get the ProductID, FrontTall and ColorImg field value without including in group by
Thanks in advance.
Kish
select new {ProductID = grouped.Max(x => x.ProductID)}
I want to perform left join using two or more table in Linq to Sql query but it looks like there is no keyword for doing so in C#. Is there any way to perform left join in the same way we do inner joins using Linq to Sql?
public IQueryable GetProducts(int productID)
{
var products =
from p in this.Products
left join c in this.ProductCategoryProducts
on p.CategoryID equals c.ProductCategoryID
left join ac in this.ProductCategories
on c.ProductCategoryID equals ac.ProductCategoryID
where p.ProductID == productID
select new
{
ProductID = a.ProductID,
Heading = p.Heading,
Category = ac.ProductCategory
};
return products ;
}
public IQueryable GetProducts(int productID)
{
var products =
from p in this.Products
join c in this.ProductCategoryProducts
on p.CategoryID equals c.ProductCategoryID into pclj
from pc in pclj.DefaultIfEmpty()
join ac in this.ProductCategories
on c.ProductCategoryID equals ac.ProductCategoryID into pcidlj
from pcid in pcidlj.DefaultIfEmpty()
where p.ProductID == productID
select new
{
ProductID = p.ProductID,
Heading = p.Heading,
Category = pcid != null ? pcid.ProductCategory : null
};
return products ;
}
Anyways I got the solution using Lambda expressions in this way:
var products =
from p in this.Products
join cat in this.ProductCategoryProducts
.Where(c => c.ProductID == p.ProductID).DefaultIfEmpty()
from pc in this.ProductCategories
.Where(pc => pc.ProductCategoryID == cat.ProductCategoryID).DefaultIfEmpty()
where p.ProductID == productID
select new
{
ProductID = p.ProductID,
Heading = p.Heading,
Category = pc.ProductCategory
};
return products ;