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)
};
Related
I have 3 simple tables
tblQual (ID, QualName)
tblPerson (ID, PersonName)
tblPersonQual (ID, PersonID, QualID, ExpiryDate)
I would like to display a matrix with PersonName down the left, QualName at the top and ExpiryDate in the middle. How do I go about doing this?
I've tried this but no joy.
var QualMatrix = from c in db.tblPersonQual
join q in db.tblQual on c.QualID equals q.ID
join p in db.tblPerson on c.PersonID equals p.ID
group c by c.ID into g
select new
{
rowKey = g.Key,
rowData = g.Select(c => new { Qual = q.QualName, Expiry = c.Expiry })
};
In terms of output view something similar to this
As my understanding, you want to display a matrix with QualName, ExpiryDate and QualName. We can use the same query by just modifying group by clause.
var QualMatrix = from c in db.tblPersonQual
join q in db.tblQual on c.QualID equals q.ID
join p in db.tblPerson on c.PersonID equals p.ID
group new { q.QualName,p.PersonName} by new { c.ID,c.ExpiryDate } into g
select new
{
QualName=g.Select(e=>e.QualName).FirstOrDefault(),
ExpirtyDate=g.Key.Expiry,
PersonName=g.Select(e=>e.PersonName).FirstOrDefault(),
};
Hopefully, This will fulfil your requirement.
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'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 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 ;
I am very new to LINQ and having great trouble grouping my tables so everything adds up together. I am trying to get this to display all the customers that have purchased more than $50 EVEN IF THEY HAVE MULTIPLE PURCHASES. in the SQL database using linq. Here is what I have so far, please help.
public class TopCustomerVM
{
public string Name { get; set; }
public decimal DollarsSold { get; set; }
public static List<TopCustomerVM> GetResults()
{
ACEEntities db = new ACEEntities();
return (from c in db.Customers
join o in db.Orders on c.CustomerId equals o.CustomerId
join l in db.OrderLines on o.OrderId equals l.OrderId
into x
select new TopCustomerVM {
Name = c.FirstName + c.LastName,
DollarsSold = x.Sum(asdf => asdf.UnitCost * asdf.Quantity)
})
.OrderByDescending(lkj => lkj.DollarsSold)
.Where(lkj => lkj.DollarsSold > 50)
.ToList();
}
}
I believe something like this will give you the desired output:
from record in
(from c in Customers
join o in Orders on c.Id equals o.CustomerId
join ol in OrderLines on o.Id equals ol.OrderId
let customerAndLine = new { Name = c.FirstName + ' ' + c.LastName, DollarsSold = ol.UnitCost * ol.Quantity }
group customerAndLine by customerAndLine.Name into grp
select new { Name = grp.Key, DollarsSold = grp.Sum(r => r.DollarsSold) })
where record.DollarsSold > 50
orderby record.DollarsSold descending
select record