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;
}
Related
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
};
I have a long result set in linq which is put in ratestest, I am mapping the result to ChargeElementsNullable. The issue is this doesnt include a fee record which is
var fees = (from r in _dbContext.Rates
where r.RateTypeFK == RateType.Fee && (r.LocaleBW & localeid) > 0 && (r.PolicyBW & policy.BitWise) > 0 && r.RateExclude == 0
select r);
So I want to add fees to ratestest and I could do that mapping again so I can use the add method, but I dont want to do that long winded mapping just for one record.. I am trying to add it to ratestest directly instead.. but no joy... I tried using DefaultIfEmpty expecting a left join.. but fee still wasnt in there..
var ratestest = (from qi in quoteInputs
join r in _dbContext.Rates on qi.RatePK equals r.RatePK
join fee in fees on r.RatePK equals fee.RatePK into feecontainer
from fee in feecontainer.DefaultIfEmpty()
join c in _dbContext.Covers on r.CoverCalcFK equals c.CoverPK into covers
from c in covers.DefaultIfEmpty()
join rt in _dbContext.RateTypes on qi.RateTypeFK equals rt.RateTypePK
where rt.Ratable == 1 ||
rt.RateTypePK == RateType.PostCode ||
rt.RateTypePK == RateType.Fee// employersliab.Contains(r.InputFK)
select new ChargeElementsNullable
{
PolicyFK = quote.PolicyFK,
InputFK = r.InputFK,
LongRate = r.LongRate,
RateLabel = r.RateLabel,
CoverName = c.CoverName,
CoverFK = r.CoverCalcFK,
CoverBW = c.BitWise,
ListRatePK = r.ListRatePK,
RatePK = r.RatePK,
RateName = r.RateName,
Rate = r.Rate,
Threshold = r.Threshold,
Excess = r.Excess,
DivBy = r.DivBy,
DiscountFirstRate = r.DiscountFirstRate,
DiscountSubsequentRate = r.DiscountSubsequentRate,
HazardRating = r.HazardRating,
TableFirstColumn = r.TableFirstColumn,
TableChildren = r.TableChildren,
RateTypeFK = r.RateTypeFK,
PageNo = r.PageNo,
SumInsured = qi.SumInsured,
NoItems = qi.NoItems,
RateValue = qi.RateValue,
TriggerCode = rt.TriggerCode,
Territory = territory
}).ToList();
You have to create a model with two properties one for quoteInputs and another for fees. Then you just need to select both of them.
Eg:
class model1
{
public QuoteInputs quoteInputs {get;set;}
public Fees fees{get;set;}
}
Then you call use this model in the select clause and assign this model tables directly.
Now let's take your code and change select like this :
var ratestest = (from qi in quoteInputs
join r in _dbContext.Rates on qi.RatePK equals r.RatePK
join fee in fees on r.RatePK equals fee.RatePK into feecontainer
from fee in feecontainer.DefaultIfEmpty()
join c in _dbContext.Covers on r.CoverCalcFK equals c.CoverPK into covers
from c in covers.DefaultIfEmpty()
join rt in _dbContext.RateTypes on qi.RateTypeFK equals rt.RateTypePK
where rt.Ratable == 1 ||
rt.RateTypePK == RateType.PostCode ||
rt.RateTypePK == RateType.Fee// employersliab.Contains(r.InputFK)
select new model1{
quoteInputs = qi,
fees = fee
}).ToList();
As you mentioned in comments, you are seeking for Concat method (MSDN). This can be done like this:
var fees = from ...
select new ChargeElementsNullable {
Prop1 = (some value),
Prop2 = (other value)
}
var ratestest = from ...
select new ChargeElementsNullable {
Prop1 = (some value),
Prop2 = (other value)
}
var bothtogether = fees.Concat(ratestest);
Be sure, that you have all properties in exactly same order and all properties are in both selects. Otherwise Linq2Sql will fail when obtaining results. (I assume from your code that you are using it)
As #Cris correctly pointed out in comments, same order is not necessary.
I've got two entities with a foreign key between them, commissions and invoices. I'm trying to use a ViewModel to include the data from the join, but I can't figure out how to cast it. If I just use the relationship mapping it does a select every time it's called, which is gross.
var commissions = from comm in db.Lead_Commission_Request
join inv in db.Lead_Referral_Invoice on comm.lead_commission_request_id equals inv.lead_commission_request_id
where inv.invoice_status_id == 0
select new InvoiceView
{
commission = comm,
invoices = inv
};
I've gotten it working using a subselect and casting to IEnumerable<>, but that still seems awkward.
var commissions = from comm in db.Lead_Commission_Request
join inv in db.Lead_Referral_Invoice on comm.lead_commission_request_id equals inv.lead_commission_request_id
where inv.invoice_status_id == 0
select new InvoiceView
{
commission = comm,
invoices = (from invb in db.Lead_Referral_Invoice where comm.lead_commission_request_id == invb.lead_commission_request_id select invb)
};
public class InvoiceView
{
public Lead_Commission_Request commission;
public IEnumerable<Lead_Referral_Invoice> invoices;
}
Use GroupBy to put your rows together:
var commissions = from comm in db.Lead_Commission_Request
join inv in db.Lead_Referral_Invoice on comm.lead_commission_request_id equals inv.lead_commission_request_id
where inv.invoice_status_id == 0
group new { comm, inv } by comm.Id into g
select new InvoiceView
{
commission = g.FirstOrDefault().comm,
invoices = g.Select(x => x.inv)
};
I cannot find a specific example of this, so am posting the question. Any help appreciated.
I have two large generic lists, both with over 300K items.
I am looping through the first list to pull back information and generate a new item for a new list on the fly, but I need to search within the second list and return a value, based on THREE matching criteria, if found to add to the list, however as you can imagine, doing this 300k * 300k times is taking time.
Is there any way I can do this more efficiently?
My code:
var reportList = new List<StocksHeldInCustody>();
foreach (var correctDepotHolding in correctDepotHoldings)
{
var reportLine = new StocksHeldInCustody();
reportLine.ClientNo = correctDepotHolding.ClientNo;
reportLine.Value = correctDepotHolding.ValueOfStock;
reportLine.Depot = correctDepotHolding.Depot;
reportLine.SEDOL = correctDepotHolding.StockCode;
reportLine.Units = correctDepotHolding.QuantityHeld;
reportLine.Custodian = "Unknown";
reportLine.StockName = correctDepotHolding.StockR1.Trim() + " " + correctDepotHolding.StockR2.Trim();
//Get custodian info
foreach (var ccHolding in ccHoldList)
{
if (correctDepotHolding.ClientNo != ccHolding.ClientNo) continue;
if (correctDepotHolding.Depot != ccHolding.Depot) continue;
if (correctDepotHolding.StockCode != ccHolding.StockCode) continue;
if (correctDepotHolding.QuantityHeld != ccHolding.QuantityHeld) continue;
reportLine.Custodian = ccHolding.Custodian;
break;
}
reportList.Add(reportLine);
}
As Pranay says, a join is probably what you want:
var query = from correct in correctDepotHoldings
join ccHolding in ccHoldList
on new { correct.ClientNo, correct.Depot,
correct.StockCode, correct.QuantityHeld }
equals new { ccHolding.ClientNo, ccHolding.Depot,
ccHolding.StockCode, ccHolding.QuantityHeld }
// TODO: Fill in the properties here based on correct and ccHolding
select new StocksHeldInCustody { ... };
var reportList = query.ToList();
You could move the data from the lookup list into a dictionary, with the key being a unique hash of the 3 items you are searching on. Then you will have very quick lookups and save millions of iterations.
Check my full post : Linq Join on Mutiple columns using Anonymous type
Make use of Linq inner join that will do work for you.
var list = ( from x in entity
join y in entity2
on new { x.field1, x.field2 }
equals new { y.field1, y.field2 }
select new entity { fields to select}).ToList();
Join of linq on multiple field
EmployeeDataContext edb= new EmployeeDataContext();
var cust = from c in edb.Customers
join d in edb.Distributors on
new { CityID = c.CityId, StateID = c.StateId, CountryID = c.CountryId,
Id = c.DistributorId }
equals
new { CityID = d.CityId, StateID = d.StateId, CountryID = d.CountryId,
Id = d.DistributorId }
select c;
Use LINQ to join the lists and return it how you like.
eg
var list1 = GetMassiveList();
var list2 = GetMassiveList();
var list3 = from a in list1
join b in list2
on new { a.Prop1, a.Prop2 } equals
new { b.Prop1, b.Prop2 }
select new { a.Prop1, b.Prop2 };
To do your outter join, you can use DefaultIfEmpty()
This example is setting your RIGHT part of the join to a default object (often null) for the cases where a join wasn't made.
eg
from a in list1
join b in list2
on new { a.Prop1, a.Prop2 } equals
new { b.Prop1, b.Prop2 }
into outer
from b in outer.DefaultIfEmpty()
select new
Prop1 = a.Prop1,
Prop2 = b != null ? b.Prop2 : "Value for Prop2 if the b join is null"
}
hi i want to select multiple db from linq in same select statement
// gets specific information from Cabinet table
var chassi = (from a in db.Cabinets
from b in db.Commodities
from e in db.sArticleNumbers
where
kjopKollonne.Contains(e.ArtNum) &&
a.ArticleNumberID == e.ID &&
a.ArticleNumberID == b.ArticleNumberID
select new {
ArtNum = e.ArtNum,
Price = b.Price,
ModelName = a.ModelName,
}).ToList();
// gets specific information from cpu table
var cpu = (from a in db.cpu
from b in db.Commodities
from e in db.sArticleNumbers
where
kjopKollonne.Contains(e.ArtNum) &&
a.ArticleNumberID == e.ID &&
a.ArticleNumberID == b.ArticleNumberID
select new {
ArtNum = e.ArtNum,
Price = b.Price,
ModelName = a.ModelName,
}).ToList();
// Joins CPU and chassi information to one output
var query1 = (from a in chassi
from b in cpu
select new {
ArtNum = a.ArtNum and b.ArtNum, <-- problem
Price = a.Price,
ModelName = a.ModelName,
}).ToList();
If any one has a different approach to solving it, thanks for posting it.
It sounds like you're looking for the Union (removes duplicates) or Concat (keeps duplicates) methods.