IQueryable LINQ ordering and grouping - sql

I have the following (incorrect) LINQ function (updated):
public IQueryable<ClassUsageReport> GetClassUsage()
{
//Class Code, Title, Usage, FiscalYear
var queryable = (from agencyplan in _agencyPlansList
join classSchedule2012 in _classSchedule2012List
on agencyplan.Id equals classSchedule2012.AgencyPlanId
join classes in _classesList
on classSchedule2012.Class.Id equals classes.Id
orderby agencyplan.PlanYear.FiscalYear descending, classes.ClassCode.Count() descending
group agencyplan by new
{
agencyplan.PlanYear.FiscalYear,
classes.ClassCode,
classes.Title
} into gcs
select new ClassUsageReport
{
ClassCode = gcs.Key.ClassCode,
Title = gcs.Key.Title,
Usage = gcs.Key.ClassCode.Count(),
FiscalYear = gcs.Key.FiscalYear
}
);
return queryable.AsQueryable();
}
I am having trouble with the Group By and Order By clauses. Also with the COUNT().
I have written the correct SQL statement, that produces the results as needed (and expected):
select py.fiscalyear, c.classcode, c.title, count(c.classcode) as usage from classschedule2012 cs
inner join classes c on cs.class_id = c.id
inner join agencyplans ap on cs.agencyplanid = ap.Id
inner join planyears py on ap.planyear_id = py.id
group by py.fiscalyear, c.classcode, c.title
order by py.fiscalyear desc, usage desc
What am I doing wrong with the grouping and ordering in my LINQ statement? I would like it to include "usage" like my SQL has. How can I get count to properly reflect the true count? As the query is at the moment, it only returns "9" in every row. This does not match my SQL, as the real results should be "55, 44, 14, 13" etc....
EDIT: 11/14/2013
Here is the final result:
public IQueryable<ClassUsageReport> GetClassUsage()
{
//Class Code, Title, Usage, FiscalYear
var queryable = (from agencyplan in _agencyPlansList
join classSchedule2012 in _classSchedule2012List
on agencyplan.Id equals classSchedule2012.AgencyPlanId
join classes in _classesList
on classSchedule2012.Class.Id equals classes.Id
where classes.Active = true
orderby agencyplan.PlanYear.FiscalYear descending
group agencyplan by new
{
agencyplan.PlanYear.FiscalYear,
classes.ClassCode,
classes.Title
} into gcs
select new ClassUsageReport
{
ClassCode = gcs.Key.ClassCode,
Title = gcs.Key.Title,
Usage = gcs.Count(),
FiscalYear = gcs.Key.FiscalYear
}
);
return queryable.AsQueryable().OrderByDescending(x => x.FiscalYear).ThenByDescending(x => x.Usage);
}

Once you group, you only have access to the columns you've grouped by and aggregate data of the other columns (like SUM or COUNT). In your query's select portion, you need to use g. instead of classes..

Try using g.Key in the select statement.

Related

How to use PredicateBuilder together with Inner Join

Database
SQL
SELECT * FROM City as a
inner join Country as b
on a.CountryCode= b.Code
where b.CountryName like %countryName%
LINQ
from city in db.Set<City>()
join country in db.Set<Country>() on city.CountryCode equals country.Code
where DbFunctions.Like(country.Name, searchParam.SearchValue)
select city;
How can I apply the LINQ into PredicateBuilder which is going use for the search function for the later on.
var Predicate = PredicateBuilder.New<City>(true);
if (!string.IsNullOrEmpty(searchParam.SearchValue))
{
switch (searchParam.SearchBy)
{
case "SearchCity":
Predicate = Predicate.And(x =>
x.Name.Contains(searchParam.SearchValue)
);
break;
default:
break;
}
}
I tested with this line in order to display all the corresponding data for my datatable
result = querys.Where(a => a.CountryCode.Contains(searchParamInString.SearchValue));
But CountryCode still didn't equals to Code because when I tried using
a.Code
it still display City doesn't contain Code

How to write join query with multiple column - LINQ

I have a situation where two tables should be joined with multiple columns with or condition. Here, I have a sample of sql query but i was not able to convert it into linq query.
select cm.* from Customer cm
inner join #temp tmp
on cm.CustomerCode = tmp.NewNLKNo or cm.OldAcNo = tmp.OldNLKNo
This is how i have write linq query
await (from cm in Context.CustomerMaster
join li in list.PortalCustomerDetailViewModel
on new { OldNLKNo = cm.OldAcNo, NewNLKNo = cm.CustomerCode } equals new { OldNLKNo = li.OldNLKNo, NewNLKNo = li.NewNLKNo }
select new CustomerInfoViewModel
{
CustomerId = cm.Id,
CustomerCode = cm.CustomerCode,
CustomerFullName = cm.CustomerFullName,
OldCustomerCode = cm.OldCustomerCode,
IsCorporateCustomer = cm.IsCorporateCustomer
}).ToListAsync();
But this query doesn't returns as expected. How do I convert this sql query into linq.
Thank you
You didn't tell if list.PortalCustomerDetailViewModel is some information in the database, or in your local process. It seems that this is in your local process, your query will have to transfer it to the database (maybe that is why it is Tmp in your SQL?)
Requirement: give me all properties of a CustomerMaster for all CustomerMasters where exists at least one PortalCustomerDetailViewModel where
customerMaster.CustomerCode == portalCustomerDetailViewModel.NewNLKNo
|| customerMaster.OldAcNo == portalCustomerDetailViewModel.OldNLKNo
You can't use a normal Join, because a Join works with an AND, you want to work with OR
What you could do, is Select all CustomerMasters where there is any PortalCustomerDetailViewModel that fulfills the provided OR:
I only transfer those properties of list.PortalCustomerDetailViewModel to the database that I need to use in the OR expression:
var checkProperties = list.PortalCustomerDetailViewModel
.Select(portalCustomerDetail => new
{
NewNlkNo = portalCustomerDetail.NewNlkNo,
OldNLKNo = portalCustomerDetail.OldNLKNo,
});
var result = dbContext.CustomerMasters.Where(customerMaster =>
checkProperties.Where(checkProperty =>
customerMaster.CustomerCode == checkProperty.NewNLKNo
|| customerMaster.OldAcNo == checkProperty.OldNLKNo)).Any()))
.Select(customerMaster => new CustomerInfoViewModel
{
Id = customerMaster.Id,
Name = customerMaster.Name,
...
});
In words: from each portalCustomerDetail in list.PortalCustomerDetailViewModel, extract the properties NewNKLNo and OldNLKNo.
Then from the table of CustomerMasters, keep only those customerMasters that have at least one portalCustomerDetail with the properties as described in the OR statement.
From every remaining CustomerMasters, create one new CustomerInfoViewModel containing properties ...
select cm.* from Customer cm
inner join #temp tmp
on cm.CustomerCode = tmp.NewNLKNo or cm.OldAcNo = tmp.OldNLKNo
You don't have to use the join syntax. Adding the predicates in a where clause could get the same result. Try to use the following code:
await (from cm in Context.CustomerMaster
from li in list.PortalCustomerDetailViewModel
where cm.CustomerCode == li.NewNLKNo || cm.OldAcNo = li.OldNLKNo
select new CustomerInfoViewModel
{
CustomerId = cm.Id,
CustomerCode = cm.CustomerCode,
CustomerFullName = cm.CustomerFullName,
OldCustomerCode = cm.OldCustomerCode,
IsCorporateCustomer = cm.IsCorporateCustomer
}).ToListAsync();
var result=_db.Customer
.groupjoin(_db.#temp ,jc=>jc.CustomerCode,c=> c.NewNLKNo,(jc,c)=>{jc,c=c.firstordefault()})
.groupjoin(_db.#temp ,jc2=>jc2.OldAcNo,c2=> c2.OldNLKNo,(jc2,c2)=>{jc2,c2=c2.firstordefault()})
.select(x=> new{
//as you want
}).distinct().tolist();

I need to transform a SQL query with inner joins to Linq in Entity Framework

I am very new to translating queries to entity, I don't know how to replace that query into linq in my code
select
brules.rule_description, brules.user_story_number,
so.source_name,
count(dlog.row_id) as error_count,
cast(execution_date as date) as execution_date
from
br.lk_business_rules brules
inner join
br.business_rules_detailed_log dlog on dlog.user_story_number = brules.user_story_number
inner join
br.lk_business_rules_source so on so.source_id = source_id_fk
where
brules.status_id_fk = 3
group by
brules.rule_description, brules.user_story_number,
so.source_name, cast(execution_date as date)
order by
brules.rule_description
i tried this:
var query = from br in _context.Lk_business_rules
join detLog in _context.Business_rules_detailed_log
on br.User_story_number equals detLog.User_story_number
join source in _context.Lk_business_rules_source
on detLog.Source_id equals source.Source_id
where br.Status_id_fk == 3
select new
{
Business_rule_description = br.Rule_description,
Business_rule_storynumber = br.User_story_number,
Source = source.Source_name,
Error_count = detLog.Row_id.Count,
Date = detLog.Execution_date
};
but not succed

Linq to SQL include related table

Been trying for a while now, but just can't get it to work the way I want. Referring to the code snippet below, I want to include a related table to Bricks (BrickColors). As of now BrickColors are not included and is lazy loaded.
var query = (from ul in DbContext.UserLocs
join l in DbContext.Locs on ul.LocId equals l.Id
join lb in DbContext.LocBricks on l.Id equals lb.LocId
join b in DbContext.Bricks on lb.BrickId equals b.Id
join bc in DbContext.BrickColors on b.ColorId equals bc.Id
where ul.UserId == userId
group new { LocQty = ul.Quantity, LocBrickQty = lb.Quantity, Brick = b } by new { b.BrickId, b.ColorId }
into data
orderby data.Key
select new
{
Brick = data.FirstOrDefault().Brick,
Quantity = data.Sum(d => d.LocBrickQty * d.LocQty)
})
.AsNoTracking();
If I remove .AsNoTracking() the performance is quite good, because it keeps the BrickColors table in memory, but I want it to be included in the query from the start.
I have tried DbContext.Bricks.Include(b => b.BrickColorAccessor) in the query, but that doesn't work. I think my group new { } is messing something up since I don't include BrickColors there...

Need help in converting SQL query to LINQ

I am new to the world of LINQ and hence I am stuck at converting one sql query to LINQ.
My SQL query is:
select COUNT(DISTINCT PAYER) as count,
PPD_COL FROM BL_REV
where BL_NO_UID = 1084
GROUP BY PPD_COL
The desired output is:
Count PPD_COL
12 P
20 C
I have written something like below in LINQ:
var PayerCount = from a in LstBlRev where a.DelFlg == "N"
group a by new { a.PpdCol} into grouping
select new
{
Count = grouping.First().PayerCustCode.Distinct().Count(),
PPdCol = (grouping.Key.PpdCol == "P") ? "Prepaid" : "Collect"
};
But it is not giving me the desired output. The count is returned same for PPD_COL value P & C. What am I missing here?
Change the groupby as following. in the group group only the property you need and then in thr by no need to create an anonymous object - just the one property you are grouping by.
var PayerCount = from a in LstBlRev
where a.DelFlg == "N"
group a.PayerCustCode by a.PpdCol into grouping
select new
{
Count = grouping.Distinct().Count(),
PPdCol = grouping.Key == "P" ? "Prepaid" : "Collect"
};