Insert Additional Condition in LINQ - sql-server

I am modifying a LINQ query in SQL Server 2014, but I have never used the syntax:
if (!UserAccessMatrixSession.HasRole(Session, Constant.ROLE_STAFF))
{
if (country != 0 )
{
ViewData["Employees"] = (from staff in db.Staffs
from jobinfo in db.JobInfo
.Where(x => x.staff_id == staff.StaffID)
.OrderByDescending(x => x.jobinfo_id).Take(1)
orderby staff.Alias
select new { staff, jobinfo }).Where(x => x.jobinfo.location == country)
.Select(x => x.staff).ToList();
}
else
{
ViewData["Employees"] = (from staff in db.Staffs
orderby staff.Alias
select staff).ToList();
}
}
I would like to insert an additional condition as follows:
where jobinfo.last_date == null OR DateTime.Now < jobinfo.last_date

I believe you would want to add that where clause into where you are selecting from the job info
if (!UserAccessMatrixSession.HasRole(Session, Constant.ROLE_STAFF))
{
if (country != 0 )
{
ViewData["Employees"] = (from staff in db.Staffs
from jobinfo in db.JobInfo
.Where(x => x.staff_id == staff.StaffID)
.OrderByDescending(x => x.jobinfo_id).Take(1)
orderby staff.Alias
select new { staff, jobinfo }).Where(x => x.jobinfo.location == country
/* last_date null or UtcNow < last_date*/ && (x.jobinfo.last_date == null || DateTime.UtcNow < jobinfo.last_date))
.Select(x => x.staff).ToList();
}
else
{
ViewData["Employees"] = (from staff in db.Staffs
orderby staff.Alias
select staff).ToList();
}
}

Related

how to join a table in asp.netcore

Here the way I join the table I want to implement it to asp.net core I don't know which is the correct way.
left join MasterHubxRangeTest mhr on hb.categoryid=mhr.hubxcatid and mhr.ItemStatus='Normal' and mhr.CountryCode='AUS' and mhr.ItemTitle = hb.ItemTitle
below line of code is how i tried to implement the same in asp.net core here im using Include() function i think this is wrong which function should i use. Here HubxDataItems, HubxDataCategory, MasterHubxRangeTest are tables. I'm trying to get the data by giving some cnditions.
The issue is only MasterHubxRangeTest table condition that I gave
var dataItems =
(from item in _context.HubxDataItems.Where(c => c.PatientId == patientId && c.IsActive == true && c.IsDeleted == false)
from category in _context.HubxDataCategory.Where(c => c.Id == item.CategoryId && c.IsActive == true && c.IsDeleted == false)
from range in _context.MasterHubxRangeTest.Include(d => d.HubXCatID == item.CategoryId && d.ItemTitle == item.ItemTitle && d.ItemStatus == "Normal" && d.CountryCode == "AUS").Where(c => c.HubXCatID == item.CategoryId && c.IsActive == true && c.IsDeleted == false)
select new
{
CategoryId = item.CategoryId,
ItemTitle = item.ItemTitle,
ItemValue = item.ItemValue,
ItemUnit = category.CategoryName.Trim().ToLower() == "notes" ? category.CategoryName : item.ItemUnit,
DisplayOrder = category.DisplayOrder,
IsActive = item.IsActive,
IsDeleted = item.IsDeleted,
CreatedDate = item.CreatedDate,
CreatedBy = item.CreatedBy,
UpdatedBy = item.UpdatedBy,
UpdatedDate = item.UpdatedDate,
PatientId = item.PatientId,
CategoryName = category.CategoryName,
NormalRange = range.ItemValue,
ItemColor = range.ItemColor
}).AsEnumerable();

LINQ Additional Filter in Select Statement

I am unfamiliar with LINQ and I am trying to modify an existing query.
Below is the code snippet and the filter that I would like to add in:
ViewData["Employees"] = emps = (from staff in db.Staffs
from jobinfo in db.JobInfo
.Where(x => x.staff_id == staff.StaffID)
.OrderByDescending(x => x.jobinfo_id).Take(1)
select new { staff, jobinfo })
.Select(x => x.staff).Distinct().OrderBy(x => x.Alias).ToList();
*** Insert Additional filter at the .Select statement above
<where (jobinfo.last_date == null)>
May I know how can it be done?
Could you please try like below and check in the third line?
.Where(x => x.staff_id == staff.StaffID && x.last_date == null)
two options one is to use && and use another where as follows
ViewData["Employees"] = emps = (from staff in db.Staffs
from jobinfo in db.JobInfo
.Where((x => x.staff_id == staff.StaffID) && (jobinfo.last_date == null))
.OrderByDescending(x => x.jobinfo_id).Take(1)
select new { staff, jobinfo })
.Select(x => x.staff).Distinct().OrderBy(x => x.Alias).ToList();
Other options would be
ViewData["Employees"] = emps = (from staff in db.Staffs
from jobinfo in db.JobInfo
.Where((x => x.staff_id == staff.StaffID)).Where(jobinfo.last_date == null)
.OrderByDescending(x => x.jobinfo_id).Take(1)
select new { staff, jobinfo })
.Select(x => x.staff).Distinct().OrderBy(x => x.Alias).ToList();

Covert Collection of Objects to Collection of Dictionary<string, object>

I'm fetching a large Amount of data from RIA Service. the return type have group of objects like RouteA, HistroyRouteA. HistroyLogRouteA all have records for different years with same Unique Key.
I have to Bind this data dynamically to a RadGridView. Always I have unknown columns in result.
For this I followed
http://blogs.telerik.com/vladimirenchev/posts/11-09-28/dynamic-binding-for-your-silverlight-applications.aspx
http://www.telerik.com/forums/rowdetailstemplate-binding-with-dynamic-data
And build My data Collection with Code :
private void OnShowPreviousYear(object parameter)
{
GridViewHeaderCell cell = parameter as GridViewHeaderCell;
var head = cell.Column.Header;
this.context.Load<Route>(this.context.GetRoutesQuery(), LoadBehavior.MergeIntoCurrent, OnRouteHistoryLoadComplete, null);
}
private void OnRouteHistoryLoadComplete(LoadOperation<Route> lo)
{
object ro = null;
if (lo.Entities != null)
{
this.context.Load<Routeshistory>(this.context.GetRouteshistoriesQuery(), LoadBehavior.MergeIntoCurrent, (lp) =>
{
Route recent = lo.Entities.FirstOrDefault();
int year =(int)recent.Hpmsyear-1;
var rows = this.context.Routes.Join(this.context.Routeshistories,
r => r.Routeid.ToString(),
h => h.Routeid.ToString(),
(r, h) => new { r, h });//.Where(t => t.r.Routeid == t.h.Routeid );
RoutesGridData = new ObservableCollection<DataRow>();
int count = 0;
foreach (var tmpR in rows)
{
//Debug.WriteLine(tmpR.r.Routeid + " -- " + tmpR.h.Routeid);
if (count < 50)
{
DataRow row = new DataRow();
if (tmpR.r is Route)
{
Type type = tmpR.r.GetType();
foreach (PropertyInfo info in type.GetProperties())
{
// Debug.WriteLine(info.Name + "--- NAME OF PRR");
var val = info.GetValue(tmpR.r, null);
if (!info.Name.Equals("EntityConflict")
&& !info.Name.Equals("ValidationErrors")
&& !info.Name.Equals("HasValidationErrors")
&& !info.Name.Equals("EntityState")
&& !info.Name.Equals("HasChanges")
&& !info.Name.Equals("IsReadOnly")
&& !info.Name.Equals("EntityActions"))
{
row[info.Name] = val;
}
}
}
// other tables...
RoutesGridData.Add(row);
}
count++;
}
}, null);
}
// var b = ro;
}
this code works fine for small record like 50 rows. but I when It try to convert all data it become slow. and screen crashes. I think this is because of Reflection. Is there any other way to convert my fetch data into Dictionary? Means I can map my table to dictionary in Entity Framework or Linq can do this for me without getting my code slow etc.
My Entities are mapped with EF 6 & I m using Deart oracle connector.
Due to reflection it was getting extremely slow so I did in during Linq query it's working for a while what data I have with me.
var rowss = this.context.Routes.Join(this.context.Routeshistories,
r => r.Routeid,
h => h.Routeid,
(r, h) => new DataRow(
(from x in r.GetType().GetProperties() select x).Where(x => x.Name != "EntityConflict"
&& x.Name != "ValidationErrors"
&& x.Name != "HasValidationErrors"
&& x.Name != "HasChanges"
&& x.Name != "EntityState"
&& x.Name != "IsReadOnly"
&& x.Name != "EntityActions")
.ToDictionary(x => x.Name, x => (x.GetGetMethod().Invoke(r, null) == null ? "" : x.GetGetMethod().Invoke(r, null))),
(from x in h.GetType().GetProperties() select x).Where(x => x.Name == head)
.ToDictionary(x => x.Name + "-" + year.ToString(), x => (x.GetGetMethod().Invoke(h, null) == null ? "" : x.GetGetMethod().Invoke(h, null))))
);// , new EqualityComparerString()
RoutesGridData = new ObservableCollection<DataRow>(rowss);

Need to convert sql statement into Entity Framework equivalent

Given the following tables:
InstrumentLogs
InstrumentLogId (PK, int, not null)
InstrumentId (FK, int, not null)
LogDate (datetime, not null)
Action (string, not null)
Instruments
InstrumentId (PK, int, not null)
CountyId (FK, int, not null)
Counties
CountyId (PK, int, not null)
StateFips (FK, int, not null)
Name (string, not null)
States
StateFips (PK, int, not null)
Name (string, not null)
I need to figure out how to write this SQL query using Entity Framework:
select s.StateName, count(*) as total
from instruments as i
join counties as c on i.CountyID = c.CountyID
join states as s on s.StateFIPS = c.StateFIPS
where i.InstrumentID in
(select i1.InstrumentId from InstrumentLogs as i1 where i1.action = 'review' and
i1.logdate in (select max(logdate) from instrumentlogs as i2 where i1.instrumentid
=i2.InstrumentID group by i2.instrumentid))
group by s.StateName
I tried something along the lines of:
_context.Instruments.Include(i => i.County.State)
.Where(i => _context.Logs.Where(l => l.Action == 'review'
&& _context.Logs.Where(l2 => l2.InstrumentId == l.InstrumentId).Max(l2 => l2.LogDate) == l.LogDate).GroupBy(i => i.County.State.Name)
.Select(g => new { State = g.Key.Name, Total = g.Count() });
However, EF doesn't like this. I wind up with the error stating that only primitive types or enumeration types are supported.
Thanks for your help.
I finally got it to work like this
var _query = _dataContext.IndexLogs.GroupBy(l => l.InstrumentId, l => l)
.Select(grp => new { Id = grp.Key, Date = grp.Max(g => g.ActionDate) });
//Prequery to find log records that match given type and action type
var _indexes = _dataContext.IndexLogs.Where(l => l.Action == type
&& _query.Contains(new { Id = l.InstrumentId, Date = l.ActionDate})).Select(i => i.InstrumentId);
var _states = _dataContext.AdvancedIndexes
.Include(i => i.County.State)
.Where(a => a.Id > 0 && _indexes.Contains(a.Id))
.GroupBy(i => new { i.County.State.Id, i.County.State.Name })
.Select(g => new { fips = g.Key.Id, name = g.Key.Name, count = g.Count() });

Query Slow in Linq, Fast in LinqPad, SQL Management Studio and SQL Profiler

I have this linq query i'm using and it's taking 50 seconds to run when i am running it my asp.net application, however the same query executes in 500ms in LinqPad and Sql Management Studio.
I even took the query from the SQL Profiler and ran it again in SQL Management Studio and it takes around 500ms. What overhead Linq could be doing, that an extra 49s??
Below is the code for reference, thanks for your help.
var rCampaign =
(from a in db.AdCreative
join h in db.AdHit on a.ID equals h.AdID into gh
join l in db.AdGroup_Location on a.AdGroupID equals l.AdGroupID into gj
from subloc in gj.DefaultIfEmpty()
from subhits in gh.DefaultIfEmpty()
where a.AdGroup.AdHost.Select(q => q.ID).Contains(rPlatform.ID) &&
a.AdGroup.AdPublisher.Select(q => q.ID).Contains(rPublisher.ID) &&
a.AdDimensionID == AdSize &&
a.AdGroup.Campaign.Starts <= rNow &&
a.AdGroup.Campaign.Ends >= rNow &&
subhits.HitType == 1 &&
(subloc == null || subloc.LocationID == rLocationID)
select new {
ID = a.ID,
Name = a.Name,
Spent = (subhits.AdDimension != null) ? ((double)subhits.AdDimension.Credit / 1000) : 0,
CampaignID = a.AdGroup.Campaign.ID,
CampaignName = a.AdGroup.Campaign.Name,
CampaignBudget = a.AdGroup.Campaign.DailyBudget
}).GroupBy(adgroup => adgroup.ID)
.Select(adgroup => new {
ID = adgroup.Key,
Name = adgroup.FirstOrDefault().Name,
Spent = adgroup.Sum(q => q.Spent),
CampaignID = adgroup.FirstOrDefault().CampaignID,
CampaignName = adgroup.FirstOrDefault().CampaignName,
CampaignBudget = adgroup.FirstOrDefault().CampaignBudget,
})
.GroupBy(q => q.CampaignID)
.Select(campaigngroup => new {
CampaignID = campaigngroup.Key,
DailyBudget = campaigngroup.FirstOrDefault().CampaignBudget,
Consumed = campaigngroup.Sum(q => q.Spent),
RemainningCredit = campaigngroup.FirstOrDefault().CampaignBudget - campaigngroup.Sum(q => q.Spent),
Ads = campaigngroup.Select(ag => new {
ID = ag.ID,
Name = ag.Name,
Spent = ag.Spent
}).OrderBy(q => q.Spent)
})
.Where(q => q.Consumed <= q.DailyBudget).OrderByDescending(q => q.RemainningCredit).First();
There are a few ways you can simplify that query:
select into lets you keep it all in query syntax.
The join ... into/from/DefaultIfMany constructs implementing left joins can be replaced with join ... into construcs representing group joins.
Some of the groups near the end cannot be empty, so FirstOrDefault is unnecessary.
Some of the where conditions can be moved up to the top before the query gets complicated.
Here's the stab I took at it. The revisions were significant, so it might need a little debugging:
var rCampaign = (
from a in db.AdCreative
where a.AdDimensionID == AdSize &&
a.AdGroup.Campaign.Starts <= rNow &&
a.AdGroup.Campaign.Ends >= rNow &&
a.AdGroup.AdHost.Select(q => q.ID).Contains(rPlatform.ID) &&
a.AdGroup.AdPublisher.Select(q => q.ID).Contains(rPublisher.ID)
join hit in db.AdHit.Where(h => h.HitType == 1 && h.LocationID == rLocationID)
on a.ID equals hit.AdID
into hits
join loc in db.AdGroup_Location
on a.AdGroupID equals loc.AdGroupID
into locs
where !locs.Any() || locs.Any(l => l.LocationID == rLocationID)
select new {
a.ID,
a.Name,
Spent = hits.Sum(h => h.AdDimension.Credit / 1000) ?? 0,
CampaignID = a.AdGroup.Campaign.ID,
CampaignName = a.AdGroup.Campaign.Name,
CampaignBudget = a.AdGroup.Campaign.DailyBudget,
} into adgroup
group adgroup by adgroup.CampaignID into campaigngroup
select new
{
CampaignID = campaigngroup.Key,
DailyBudget = campaigngroup.First().CampaignBudget,
Consumed = campaigngroup.Sum(q => q.Spent),
RemainingCredit = campaigngroup.First().CampaignBudget - campaigngroup.Sum(q => q.Spent),
Ads = campaigngroup.Select(ag => new {
ag.ID,
ag.Name,
ag.Spent,
}).OrderBy(q => q.Spent)
} into q
where q.Consumed <= q.DailyBudget
orderby q.RemainingCredit desc)
.First()
I refactored using Query syntax (Not sure if it improved readability). Removed one group by. Made some minor adjustments (replaced FirstOrDefault with Key property, changed Contains to Any). Hopefully it has some effect of speed.
var rCampaign = (from cg in
(from a in db.AdCreative
from subhits in db.AdHit.Where(h => a.ID == h.AdID)
.DefaultIfEmpty()
from subloc in db.AdGroup_Location.Where(l => a.AdGroupID == l.AdGroupID)
.DefaultIfEmpty()
where a.AdGroup.AdHost.Any(q => q.ID == rPlatform.ID) &&
a.AdGroup.AdPublisher.Any(q => q.ID == rPublisher.ID) &&
a.AdDimensionID == AdSize &&
a.AdGroup.Campaign.Starts <= rNow &&
a.AdGroup.Campaign.Ends >= rNow &&
subhits.HitType == 1 &&
(subloc == null || subloc.LocationID == rLocationID)
group new { a, subhits } by new { ID = a.ID, a.Name, CampaignID = a.AdGroup.Campaign.ID, CampaignName = a.AdGroup.Campaign.Name, CampaignBudget = a.AdGroup.Campaign.DailyBudget } into g
select new
{
ID = g.Key.ID,
Name = g.Key.Name,
Spent = g.Sum(x => (x.subhits.AdDimension != null) ? ((double)subhits.AdDimension.Credit / 1000) : 0),
CampaignID = g.Key.CampaignID,
CampaignName = g.Key.CampaignName,
CampaignBudget = g.Key.CampaignBudget
})
group cg by new { cg.CampaignID, cg.CampaignBudget } into cg
let tempConsumed = cg.Sum(q => q.Spent)
let tempRemainningCredit = cg.Key.CampaignBudget - tempConsumed
where tempConsumed <= cg.Key.CampaignBudget
orderby tempRemainningCredit desc
select new
{
CampaignID = cg.Key.CampaignID,
DailyBudget = cg.Key.CampaignBudget,
Consumed = tempConsumed,
RemainningCredit = tempRemainningCredit,
Ads = from ag in cg
orderby ag.Spent
select new
{
ID = ag.ID,
Name = ag.Name,
Spent = ag.Spent
}
}).First();

Resources