how to join a table in asp.netcore - sql-server

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();

Related

Convert SQL query to Linq2db

Some one help me to convert SQL query to linq2db join query.
Below is my query.
var query = from a in _accountRepository.Table
join b in _documentRepository.Table on a.ID equals b.AccountID
join c in _documentTypeRepository.Table on b.DocumentTypeID equals c.ID
where a.CompanyID == companyID && b.CompanyID == companyID
&& c.CompanyID == companyID
&& a.IsActive && !a.IsDeleted && c.IsInvoice
&& b.IsActive && !b.IsDeleted
&& b.Date.Date >= fromDate.Date && b.Date.Date <=
toDate.Date
&& (b.AccountID == accountID || accountID == null)
&& (costcenterID.Contains(b.CostCenterID) || costcenterID == null)
&& a.AccountTypeID == (int)DefaultAccountTypes.Customer
group b by new { a.DisplayName, a.ID } into g
select new SalesByCustomerModel
{
AccountID = g.Key.ID,
DisplayName = g.Key.DisplayName,
InvoiceCount = g.Count(),
Sales = g.Sum(x => (x.SubTotal - x.Discount)),
SalesWithTax = g.Sum(x => x.Total),
Tax = g.Sum(x => x.Tax)
};
I have to add this. How can I achive with linq2db.
INNER JOIN ( SELECT ROW_NUMBER() OVER(PARTITION by DocumentID ORDER BY DocumentID) AS SrNo,
DocumentID
FROM DocumentDetail
WHERE (DocumentItemID = #itemID OR #itemID IS NULL)
AND CompanyID = #companyID ) D ON D.DocumentID = B.ID AND SrNo = 1
Linq2db supports window functions, and we can write details subquery and add join:
var details =
from d in _documentDetailRepository.Table
where (d.DocumentItemID == itemID || itemID == null)
&& d.CompanyID == companyID
select new
{
d.DocumentID,
SrNo = Sql.Ext.RowNumber().Over()
.PartitionBy(d.DocumentID)
.OrderBy(d.DocumentID)
.ToValue()
};
// Then your query can be extended
var query =
from a in _accountRepository.Table
join b in _documentRepository.Table on a.ID equals b.AccountID
join d in details on new { DocumentID = b.Id, SrNo = 1 } equals new { d.DocumentID, d.SrNo }
...

Insert Additional Condition in LINQ

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();
}
}

Avoid duplicate records in linq query while joining multiple tables

I have following tabes in my DB
TestPack { id, name, type }
Documentation { id, tp_id, date, rev }
Flushing { id, tp_id, date, rev }
tp_Id is the TestPack ID and is the foreign key in both Documentation and Flushing tables which means a TestPack may have 1-N Documentations and Flushings.
Now I want to query the database (using EF LINQ) to return tests packs, and all their Documentations and Flushings against one Test Pack so that I can show all this information in a single DataGrid?
Test Packs, that dont have any Documentatoin/Flushings should also show up in the result.
Here is my query that I have written so far
internal List<TestPackRegister> GenerateReport2()
{
var allTestPacks = Project.GetAllTestPacks();
var allDocumentation = Project.GetAllDocoumentations();
var allFlushings = Project.GetAllPreTestFlushings();
var queryResult = from tp in allTestPacks
join doc in allDocumentation on tp.id equals doc.test_pack_id.Value
into tpDoc
from subtpDoc in tpDoc.DefaultIfEmpty()
join flushings in allFlushings on tp.id equals flushings.test_pack_id.Value
into tpFlings
from subtpflushings in tpFlings.DefaultIfEmpty()
select new TestPackRegister
{
test_pack_no = tp.test_pack_no,
Documentation_Notification = subtpDoc != null ? subtpDoc.const_notification_no : null,
Documentation_Rev = subtpDoc != null ? subtpDoc.const_notification_no_rev : null,
Documentation_Notification_Date = subtpDoc != null ? subtpDoc.const_notification_date : null,
Documentation_TargetReadiness_Date = subtpDoc != null ? subtpDoc.doc_readiness_target_date : null,
Documentation_ActualReadiness_Date = subtpDoc != null ? subtpDoc.doc_readiness_date : null,
Documentation_Remarks = subtpDoc != null ? subtpDoc.remarks : null,
Flushing_RFI = subtpflushings != null ? subtpflushings.RFINo : null,
Flushing_Rev = subtpflushings != null ? subtpflushings.rfi_rev_no : null,
Flushing_RFI_Date = subtpflushings != null && subtpflushings.rfi_date != null ? subtpflushings.rfi_date : null,
Flushing_Planned_Date = subtpflushings != null && subtpflushings.planned_date != null ? subtpflushings.planned_date : null,
Flushing_Actual_Date = subtpflushings != null && subtpflushings.actual_date != null ? subtpflushings.actual_date : null,
Flushing_Acceptance_Date = subtpflushings != null && subtpflushings.acceptance_date != null ? subtpflushings.acceptance_date : null,
Flushing_Remarks = subtpflushings != null ? subtpflushings.remarks : null,
};
QueryResult = queryResult.ToList();
return QueryResult;
}
And here is the result of the query
Basically in my TestPack table, I have 2 testPacks.
Test Pack 1 has 2 Documentations and 2 Flushing records while Test Pack 2 has only 1 Documentation and 1 Flushing record.
So my concern here is that TestPack # 1 is showing four rows, Should not it be showing two rows? because the test pack has 2 flushings and 2 documentation for 1 testPack. so all of them should appear in 2 rows? Why they are appearing as four rows? And how can I correct this behavior?
I'm stuck in this too. This is my approach:
foreach (var tp in allTestPacks)
{
var lstAllFlh = allFlushings.Where(m => m.TpID == tp.IDTP).ToList();
var lstAllDoc = allDocumentation.Where(m => m.TpID == tp.IDTP).ToList();
foreach (var flh in lstAllFlh)
lstResult.Add(new { TPID = tp.IDTP, TPName = tp.Value, DocName = lstAllDoc.Skip(lstAllFlh.FindIndex(f => f == flh) % lstAllDoc.Count).First().Value, FlushName = flh.Value });
}

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);

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