Convert Sql to LINQ complex C# function to readable sql server string - c#

I read a lot about getting a readable sql server query string from a c# linq to sql function, but could not figure out how to actually do so, maybe because the project i am working on is really complicated.
I'm pasting a pice of a code that i want to convert to sql (select * from bonds join etc.)
public List<EntBondPortfolio> GetBondsForPortfolio(List<int> groups, List<int> ratings,
List<int> collaterals, List<int> companies, List<int> countries, List<int> fields,
List<int> currencies, DateTime? fromExpirationDate, DateTime? untilExpirationDate, bool? perpetual, int? sortOrder = 1)
{
// Get Bonds
return (from bond in DALLinqClasses.Instance.BONDs
join company in DALLinqClasses.Instance.COMPANies on bond.Company_ID equals company.CompanyID
into companyJoin
from companyJ in companyJoin.DefaultIfEmpty()
join sellBuy in DALLinqClasses.Instance.SELL_BUY_OPERATIONs on bond.BondID equals sellBuy.Investment_ID
join account in DALLinqClasses.Instance.BANK_ACCOUNTs on sellBuy.BankAccount_ID equals account.BankAccountID
join groupsTable in DALLinqClasses.Instance.GROUPs on account.GroupAccount_ID equals groupsTable.GroupID
join customer in DALLinqClasses.Instance.CUSTOMERs on groupsTable.Customer_ID equals customer.CustomerID
join rating in DALLinqClasses.Instance.RATINGs on bond.Rating_ID equals rating.RatingID
into ratingJoin
from ratingJ in ratingJoin.DefaultIfEmpty()
join currency in DALLinqClasses.Instance.CURRENCies on bond.Currency_ID equals currency.CurrencyID
join country in DALLinqClasses.Instance.COUNTRies on bond.Country_ID equals country.CountryID
into countryJoin
from countryJ in countryJoin.DefaultIfEmpty()
join field in DALLinqClasses.Instance.FIELDs on bond.Field_ID equals field.FieldID
into fieldJoin
from fieldJ in fieldJoin.DefaultIfEmpty()
join collateral in DALLinqClasses.Instance.RISC_LEVELs on bond.RiscLevel_ID equals collateral.RiscLevelID
into collateralJoin
from collateralJ in collateralJoin.DefaultIfEmpty()
join orderi in // For order by
DALLinqClasses.Instance.PORTFOLIO_ORDERs.Where(x => x.InvestmentType_ID == (int)INVESTMENT_TYPES.BONDS)
on new EntTwoInts { BankAccountID = bond.BondID, GroupID = groupsTable.GroupID }
equals
new EntTwoInts { BankAccountID = orderi.Investment_ID, GroupID = orderi.Group_ID }
into orderJoin
from orderJ in orderJoin.DefaultIfEmpty()
where sellBuy.InvestmentType_ID == (int)INVESTMENT_TYPES.BONDS
&& groups.Contains(groupsTable.GroupID)
&& (collaterals.Contains(bond.RiscLevel_ID ?? -1) || collaterals.Contains(-1))
&& (ratings.Contains(bond.Rating_ID ?? -1) || ratings.Contains(-1))
&& (companies.Contains(bond.Company_ID ?? -1) || companies.Contains(-1))
&& (countries.Contains(bond.Country_ID ?? -1) || countries.Contains(-1))
&& (fields.Contains(bond.Field_ID ?? -1) || fields.Contains(-1))
&& (currencies.Contains(bond.Currency_ID) || currencies.Contains(-1))
&& (bond.ExpirationDate >= fromExpirationDate || fromExpirationDate == null)
&& (bond.ExpirationDate <= untilExpirationDate || untilExpirationDate == null)
&& (perpetual == bond.Perpetual || perpetual == null)
group sellBuy by new { bond, companyJ, groupsTable, account, orderJ, customer, ratingJ, collateralJ, countryJ, fieldJ } into g
orderby g.Key.orderJ != null ? false : true, g.Key.orderJ.SortOrder, g.Key.groupsTable.GroupName, g.Key.companyJ.CompanyName
select new EntBondPortfolio
{
Rating = g.Key.ratingJ.RatingName,
RiscLevel = g.Key.collateralJ.RiscLevelName,
Group = g.Key.groupsTable.GroupName,
Client = g.Key.customer.FirstName + ' ' + g.Key.customer.LastName,
GroupId = g.Key.groupsTable.GroupID,
Company = g.Key.companyJ.CompanyName,
CurrencyId = g.Key.bond.Currency_ID,
BondId = g.Key.bond.BondID,
CallText = g.Key.bond.CallText,
Field = g.Key.fieldJ.FieldName,
Country = g.Key.countryJ.CountryName,
CouponPercent = g.Key.bond.CouponPercent,
// Get total sum of coupons in checking account of current bond
CouponsPaid = DALLinqClasses.Instance.CHECKING_ACCOUNTs.
Where(x => x.ActionType_ID == (int)ACTION_TYPES.COUPON
&& g.Select(y => y.SellBuyOperationID).
Contains(x.SellBuyOperation_ID.GetValueOrDefault()))
.Sum(s => s.ActualSum),
ExpirationDate = g.Key.bond.ExpirationDate,
FaceValue = (g.Where(x => x.IsSell == false).Sum(x => x.FaceValue) - (g.Where(x => x.IsSell == true).Sum(x => x.FaceValue) ?? 0)),
Isin = g.Key.bond.Isin,
LastBuyDate = g.Where(x => x.IsSell == false).Max(x => x.SellBuyOperationDate),
CurrentPrice = DALInvestmentTypes.Instance.GetCurrentPriceOfBond(g.Key.bond.BondID, BONDS_HISTORY_TYPES.MarketValue),
CurrentYield = DALInvestmentTypes.Instance.GetCurrentPriceOfBond(g.Key.bond.BondID, BONDS_HISTORY_TYPES.Yield),
CurrentAcrInterest = DALInvestmentTypes.Instance.GetCurrentPriceOfBond(g.Key.bond.BondID, BONDS_HISTORY_TYPES.AcrInterest),
PurchasePrice = g.Where(x => x.IsSell == false).Sum(x => x.FaceValue) == 0 ? 0 :
g.Where(x => x.IsSell == false).Sum(x => x.FaceValue * x.Price)
/ g.Where(x => x.IsSell == false).Sum(x => x.FaceValue),
Instruction = DALInstructions.Instance.IsInvestmentHaveInstruction(INVESTMENT_TYPES.BONDS, g.Key.bond.BondID, g.Key.account.BankAccountID),
}).ToList();
}

Related

Turning off part of long running Entity Framework query conditionally

In my Asp.Net Web Api project, there's a GET method to fetch all processes. Process in my app is an entity to log various maintenence activities, it has many properties, e.g. beginning and end. Each processes can be handled by many users and so single Process can have many Handlings associated with it. Each handling also has begining and end timestamps. Recently I added "HandlingsLength" property to calculate for each process its handlings length. Unfortunately, adding this property made all requests targeting the method run almost twice as long..
Now, I'm looking for a way to improve the execution time of my method, either by complete rewrite, or by using some smart workaround. There are requests which doesn't mind waiting long for response, but there are also requests that don't need this property calculated and need to be fast too. My first idea was passing handlingsLength argument to my method and depending on its value HandlingsLength would be calculated or just set to null.
HandlingsLength = handlingsLength == null || handlingsLength == false ? null : grp.Where(ph => ph.ha.HandlingId > 0).Sum(h => DbFunctions.DiffMinutes(h.ha.StartedOn, h.ha.FinishedOn)) == null ? grp.Where(ph => ph.ha.HandlingId > 0).Sum(h => DbFunctions.DiffMinutes(h.ha.StartedOn, DateTime.Now)) : grp.Where(ph => ph.ha.HandlingId > 0).Sum(h => DbFunctions.DiffMinutes(h.ha.StartedOn, h.ha.FinishedOn))
Unfortunately it doesn't work, even if I pass handlingsLenght=null to indicate this property shouldn't be calculated, run time is more-less the same. Probably my linq statement is compiled to SQL at compilation so it doesn't know the value parameter provided on runtime. If there's a way to effectively 'turn off' this property at runtime, it's very welcome.
Here's complete body of my linq to entity statement:
items = (from p in db.JDE_Processes
join uuu in db.JDE_Users on p.FinishedBy equals uuu.UserId into finished
from fin in finished.DefaultIfEmpty()
join t in db.JDE_Tenants on p.TenantId equals t.TenantId
join u in db.JDE_Users on p.CreatedBy equals u.UserId
join at in db.JDE_ActionTypes on p.ActionTypeId equals at.ActionTypeId
join uu in db.JDE_Users on p.StartedBy equals uu.UserId into started
from star in started.DefaultIfEmpty()
join lsu in db.JDE_Users on p.LastStatusBy equals lsu.UserId into lastStatus
from lStat in lastStatus.DefaultIfEmpty()
join pl in db.JDE_Places on p.PlaceId equals pl.PlaceId
join comp in db.JDE_Components on p.ComponentId equals comp.ComponentId into comps
from components in comps.DefaultIfEmpty()
join s in db.JDE_Sets on pl.SetId equals s.SetId
join a in db.JDE_Areas on pl.AreaId equals a.AreaId
join h in db.JDE_Handlings on p.ProcessId equals h.ProcessId into hans
from ha in hans.DefaultIfEmpty()
where p.TenantId == TenantId && p.CreatedOn >= dFrom && p.CreatedOn <= dTo
group new { p, fin, t, u, at, started, lastStatus, lStat, pl, s, a, ha }
by new
{
p.ProcessId,
p.Description,
p.StartedOn,
p.StartedBy,
p.FinishedOn,
p.FinishedBy,
p.PlannedFinish,
p.PlannedStart,
p.PlaceId,
pl.SetId,
SetName = s.Name,
pl.AreaId,
AreaName = a.Name,
pl.Image,
p.Reason,
p.CreatedBy,
CreatedByName = u.Name + " " + u.Surname,
p.CreatedOn,
p.ActionTypeId,
p.Output,
p.InitialDiagnosis,
p.RepairActions,
p.TenantId,
p.MesId,
p.MesDate,
p.Comment,
TenantName = t.TenantName,
p.IsActive,
p.IsCompleted,
p.IsFrozen,
p.IsSuccessfull,
p.IsResurrected,
ActionTypeName = at.Name,
FinishedByName = fin.Name + " " + fin.Surname,
StartedByName = star.Name + " " + star.Surname,
PlaceName = pl.Name,
ComponentId = p.ComponentId,
ComponentName = components.Name,
LastStatus = p.LastStatus == null ? (ProcessStatus?)null : (ProcessStatus)p.LastStatus, // Nullable enums handled
p.LastStatusBy,
LastStatusByName = lStat.Name + " " + lStat.Surname,
p.LastStatusOn
} into grp
orderby grp.Key.CreatedOn descending
select new Process
{
ProcessId = grp.Key.ProcessId,
Description = grp.Key.Description,
StartedOn = grp.Key.StartedOn,
StartedBy = grp.Key.StartedBy,
StartedByName = grp.Key.StartedByName,
FinishedOn = grp.Key.FinishedOn,
FinishedBy = grp.Key.FinishedBy,
FinishedByName = grp.Key.FinishedByName,
ActionTypeId = grp.Key.ActionTypeId,
ActionTypeName = grp.Key.ActionTypeName,
IsActive = grp.Key.IsActive,
IsFrozen = grp.Key.IsFrozen,
IsCompleted = grp.Key.IsCompleted,
IsSuccessfull = grp.Key.IsSuccessfull,
PlaceId = grp.Key.PlaceId,
PlaceName = grp.Key.PlaceName,
PlaceImage = grp.Key.Image,
SetId = grp.Key.SetId,
SetName = grp.Key.SetName,
AreaId = grp.Key.AreaId,
AreaName = grp.Key.AreaName,
Output = grp.Key.Output,
TenantId = grp.Key.TenantId,
TenantName = grp.Key.TenantName,
CreatedOn = grp.Key.CreatedOn,
CreatedBy = grp.Key.CreatedBy,
CreatedByName = grp.Key.CreatedByName,
MesId = grp.Key.MesId,
InitialDiagnosis = grp.Key.InitialDiagnosis,
RepairActions = grp.Key.RepairActions,
Reason = grp.Key.Reason,
MesDate = grp.Key.MesDate,
Comment = grp.Key.Comment,
ComponentId = grp.Key.ComponentId,
ComponentName = grp.Key.ComponentName,
PlannedStart = grp.Key.PlannedStart,
PlannedFinish = grp.Key.PlannedFinish,
LastStatus = grp.Key.LastStatus,
LastStatusBy = grp.Key.LastStatusBy,
LastStatusByName = grp.Key.LastStatusByName,
LastStatusOn = grp.Key.LastStatusOn,
IsResurrected = grp.Key.IsResurrected,
OpenHandlings = grp.Where(ph => ph.ha.HandlingId > 0 && (ph.ha.IsCompleted == null || ph.ha.IsCompleted == false)).Count(),
AllHandlings = grp.Where(ph => ph.ha.HandlingId > 0).Count(),
AssignedUsers = (from pras in db.JDE_ProcessAssigns
join uu in db.JDE_Users on pras.UserId equals uu.UserId
where pras.ProcessId == grp.Key.ProcessId
select uu.Name + " " + uu.Surname),
GivenTime = givenTime == null || givenTime == false ? 0 : (from prac in db.JDE_ProcessActions
join a in db.JDE_Actions on prac.ActionId equals a.ActionId
where prac.ProcessId == grp.Key.ProcessId
select a.GivenTime).Sum(),
FinishRate = finishRate == null || finishRate == false ? 0 : db.JDE_ProcessActions.Count(i => i.ProcessId == grp.Key.ProcessId)==0
? 100 : (((float)db.JDE_ProcessActions.Count(i => i.ProcessId == grp.Key.ProcessId && i.IsChecked == true)
/ (float)db.JDE_ProcessActions.Count(i => i.ProcessId == grp.Key.ProcessId))*100),
HasAttachments = db.JDE_FileAssigns.Any(f => f.ProcessId == grp.Key.ProcessId),
HandlingsLength = handlingsLength == null || handlingsLength == false ? null : grp.Where(ph => ph.ha.HandlingId > 0).Sum(h => DbFunctions.DiffMinutes(h.ha.StartedOn, h.ha.FinishedOn)) == null ? grp.Where(ph => ph.ha.HandlingId > 0).Sum(h => DbFunctions.DiffMinutes(h.ha.StartedOn, DateTime.Now)) : grp.Where(ph => ph.ha.HandlingId > 0).Sum(h => DbFunctions.DiffMinutes(h.ha.StartedOn, h.ha.FinishedOn))
});

Linq Query Throws Timeout in code but Works fine on LinqPad

When I run the Linq query on LinqPad it takes only 4-5 seconds to return 5000 rows but when I run that same query in my code using Entity Framework it throws timeout.
What could be the possible issues?
Thanks in advance.
Below is the query:
var resultSale =
from product in Products
join productInfo in ProductInfoSummaries on product.ID equals productInfo.ProductID
join productDetail in ProductDetails on new { Id = product.ID, storeId = product.CreatedInStore } equals new { Id = productDetail.ProductID, storeId = productDetail.StoreID }
join productInventoryOtherStore in InventoryOtherStores on product.ID equals productInventoryOtherStore.ProductID
into productInventories
from productInventoryOtherStore in productInventories.DefaultIfEmpty()
join saleLine in SaleLines on productDetail.ID equals saleLine.ArtikkelNr
join sales in Sales on saleLine.OrderID equals sales.ID
where saleLine.ArtikkelNr != null
&& saleLine.DatoTid >= new DateTime(2018, 01, 01)
&& saleLine.DatoTid <= new DateTime(2019,11,21)
&& sales.StoreID == 14
&& (sales.OrderType == 1 || sales.OrderType == 2 || sales.OrderType == 4 || sales.OrderType == 6)
&& productDetail.SupplierProductNo != null
&& productDetail.Deleted == null
&& (productInfo.Inactive == null || productInfo.Inactive == false)
&& (product.CreatedInStore == 14 || product.CreatedInStore == 0 || product.CreatedInStore == null)
group new { saleLine.AntallEnheter, sales.OrderType } by new { product.ID, productInventoryOtherStore.Amount } into g
select new ProductSaleSummaryVM
{
ID = g.Key.ID,
Inventory = (double)g.Key.Amount,
TotalSold = g.Sum(x => x.OrderType !=4 ? x.AntallEnheter : 0) ?? 0,
TotalWastage = g.Sum(x => x.OrderType ==4 ? x.AntallEnheter : 0) ?? 0,
TotalOrderedQty = 0
};
var resultSupplierOrder =
from supplierOrderLine in SupplierOrderLines
join supplierOrder in SupplierOrders on supplierOrderLine.SupplierOrderID equals supplierOrder.ID
where supplierOrderLine.Deleted == null
&& supplierOrder.Status != 1
&& supplierOrder.StoreID == 14
group supplierOrderLine by supplierOrderLine.ProductID into g
select new ProductOrderDetailsVM
{
ID = g.Key,
TotalOrderedQty = (double)g.Sum(x => x.ConsumerQuantity - x.QuantiyReceived)
};
var r =
(from resSale in resultSale
join resSupplierOrder in resultSupplierOrder on resSale.ID equals resSupplierOrder.ID
into resSupplierOrders
from resSupplierOrder in resSupplierOrders.DefaultIfEmpty()
orderby resSale.ID
select new ProductSaleSummaryVM
{
ID = resSale.ID,
Inventory = resSale.Inventory,
TotalSold = resSale.TotalSold,
TotalWastage = resSale.TotalWastage,
TotalOrderedQty = resSupplierOrder.TotalOrderedQty ?? 0
})
.Where(x => x.Inventory + x.TotalOrderedQty < x.TotalSold);
r.Dump();
Try using entity framework within linqpad see if it gives you any clues. see this link on how to use entity framework in linqpad
https://www.linqpad.net/EntityFramework.aspx
This behaviour could be related to parameter sniffing - check this article for details

How to assign stored procedure result to a entity inside select statement in entity framework

I want to assign GetMajorMileStone(projecttask.ProjectTaskId) result to MajorMilestone.
I tried but getting following error:
LINQ to Entities does not recognize the method
'System.Data.Objects.ObjectResult1[.Poco.GetMajorMileStone_Result]
GetMajorMileStone(System.Nullable1[System.Guid])' method, and this
method cannot be translated into a store expression.'
Here is my code:
public ProjectsPayload GetProjectSchedule(int projectid, bool includeArchived, DateTime startDate, DateTime endDate, int userId)
{
using (var db = new Entities())
{
try
{
db.CommandTimeout = 1200;
var query = from project in db.Project.Where(t => (t.Active || t.TempActive) && t.ProjectId == projectid)
join UP in db.User_X_Project on project.ProjectId equals UP.ProjectId
where (UP.UserId == userId && UP.Active)
orderby (project.Priority ?? int.MaxValue)
orderby (project.ProjectTitle)
select new
{
Project = project,
ProjectTask = from projecttask in project.ProjectTask.Where(t => t.Active && (
(includeArchived == true && t.TaskStatusId == (int?)TaskStatus.Archived) ||
(includeArchived == false && t.TaskStatusId != (int?)TaskStatus.Archived))
|| t.TaskStatusId != (int?)TaskStatus.Planned)
join schedule in project.ProjectTask.SelectMany(p => p.ProjectTaskSchedule) on projecttask.ProjectTaskId equals schedule.ProjectTaskId
join daily in db.ProjectTaskSchedule.SelectMany(p => p.DailyStatus) on schedule.ProjectTaskScheduleId equals daily.ProjectTaskScheduleId
where schedule.Active && daily.Active && projecttask.Active && schedule.ResourceId == userId && (
(EntityFunctions.TruncateTime(daily.Date) >= EntityFunctions.TruncateTime(startDate.Date) &&
EntityFunctions.TruncateTime(daily.Date) <= EntityFunctions.TruncateTime(endDate.Date))
)
orderby schedule.StartDate
select new
{
ProjectTask = projecttask,
ProjectTaskSchedule = from projecttaskschedule in projecttask.ProjectTaskSchedule.Where(t => t.Active && t.ResourceId == userId)
select new
{
ProjectTaskSchedule = projecttaskschedule,
DailyStatus = projecttaskschedule.DailyStatus.Where(t => t.Active),
},
CritiCality = from cr in db.CritiCality.Where(ts => ts.ProjectTaskId == projecttask.ProjectTaskId) select cr,
MMDetails = from mm in db.MMDetails.Where(ts => ts.ProjectTaskId == projecttask.ProjectTaskId) select mm,
MajorMilestone = db.GetMajorMileStone(projecttask.ProjectTaskId).FirstOrDefault(),
}
};
var materialized = query.AsEnumerable();
var result = materialized.Select(t => new ProjectsPayload
{
ProjectId = t.Project.ProjectId,
ProjectTitle = t.Project.ProjectTitle,
Priority = t.Project.Priority,
ProjectDescription = t.Project.ProjectDescription,
ProjectTask = t.Project.ProjectTask.Select(x => new ProjectTaskPayload
{
Duration = x.Duration,
Hours = x.Hours,
IsOngoing = x.IsOngoing,
IsSummaryTask = x.IsSummaryTask,
Priority = x.Priority,
ParentTaskId = x.ParentTaskId,
ProjectId = x.ProjectId,
ProjectTaskId = x.ProjectTaskId,
TaskAcceptanceId = x.TaskAcceptanceId,
TaskStatusId = x.TaskStatusId,
TaskTitle = x.TaskTitle,
TaskTypeId = x.TaskTypeId,
IsMileStone = x.IsMileStone,
IsTimeAwayTask = x.IsTimeAwayTask,
AutoSize = x.AutoSize,
IsArchivedTasksInSummary = x.IsArchivedTasksInSummary,
IsASAP = x.IsASAP,
IsAutoCompleteEnable = x.IsAutoCompleteEnable,
IsSharedDiffSchedules = x.IsSharedDiffSchedules,
LongDescription = x.LongDescription,
OwnerId = x.OwnerId,
ShowInSummaryTask = x.ShowInSummaryTask,
SubTypeID = x.SubTypeID,
MMDetails1 = x.MMDetails1.Select(MD => new MMDetailsPayload { MajorMilestoneId = MD.MajorMilestoneId, ProjectTaskId = MD.ProjectTaskId, MMDetailsId = MD.MMDetailsId, Slack = MD.Slack }),
ProjectTaskSchedule = x.ProjectTaskSchedule.Select(a => new ProjectsTaskSchedulePayload
{
ProjectTaskScheduleId = a.ProjectTaskScheduleId,
StartDate = a.StartDate,
EndDate = a.EndDate,
ProjectTaskId = a.ProjectTaskId,
ResourceId = a.ResourceId,
ArchiveEndDate = a.ArchiveEndDate,
ArchiveStartDate = a.ArchiveStartDate,
IsSharedTask = a.IsSharedTask,
TimeUnitId = a.TimeUnitId,
DailyStatus = a.DailyStatus.Select(Ds => new DailyStatusPayload
{
Active = Ds.Active,
ActualHours = Ds.ActualHours,
DailyStatusId = Ds.DailyStatusId,
Date = Ds.Date,
ProjectTaskScheduleId = Ds.ProjectTaskScheduleId,
IsCloseOutDay = Ds.IsCloseOutDay,
Priority = Ds.Priority
})
}).ToList(),
CritiCality = x.CritiCality.Select(c => new CriticalityPayload { CriticalityId = c.CriticalityId, CriticalityTypeId = c.CriticalityTypeId, ProjectTaskId = c.ProjectTaskId }).ToList(),
}).ToList()
}).FirstOrDefault();
return result;
}
catch (EntityException ex)
{
if (ex.Message == connectionException)
throw new FaultException(dbException);
else
throw new FaultException(ex.Message);
}
}
}
My result is like this, I want all entities(Criticality,MMDetails and MajorMileStone), Not only MajorMileStone
MajorMileStone Result
I separate multiple simple query for testing. Please try to execute below two query and check whether successful or not.
// First query to get project
var query1 = from project in db.Project.Where(t => (t.Active || t.TempActive) && t.ProjectId == projectid)
join UP in db.User_X_Project on project.ProjectId equals UP.ProjectId
where (UP.UserId == userId && UP.Active)
orderby (project.Priority ?? int.MaxValue)
orderby (project.ProjectTitle)
.Select new { project = project }.ToList();
// Second query to get projecttask from query1.project and execute store procedure
var query2 = from projecttask in query1.project.ProjectTask.Where(t => t.Active && (
(includeArchived == true && t.TaskStatusId == (int?)TaskStatus.Archived) ||
(includeArchived == false && t.TaskStatusId != (int?)TaskStatus.Archived)) ||
t.TaskStatusId != (int?)TaskStatus.Planned)
join schedule in query1.project.ProjectTask.SelectMany(p => p.ProjectTaskSchedule) on projecttask.ProjectTaskId equals schedule.ProjectTaskId
join daily in db.ProjectTaskSchedule.SelectMany(p => p.DailyStatus) on schedule.ProjectTaskScheduleId equals daily.ProjectTaskScheduleId
where schedule.Active && daily.Active && projecttask.Active && schedule.ResourceId == userId && (
(EntityFunctions.TruncateTime(daily.Date) >= EntityFunctions.TruncateTime(startDate.Date) &&
EntityFunctions.TruncateTime(daily.Date) <= EntityFunctions.TruncateTime(endDate.Date))
)
orderby schedule.StartDate
.Select new
{
MajorMilestone = db.GetMajorMileStone(projecttask.ProjectTaskId).FirstOrDefault(),
}.ToList();
Let me know it has result or not. In the meantime you can check this "Method cannot be translated into a store expression"
It has link to article about what not to do with linq. Nested Linq like this is best to avoid and better to split up the query. If it affects the execution time, it better to execute raw sql.

Converting SQL to LINQ C# to return data with most recent entry of a field

I'm trying to convert this to LINQ C#. I am expecting a single result with the most recent data but the LINQ returns 3 results with the individual data.
SQL:
select * from ticket t
join tollBoothShift tbs on t.fkTollBoothShift = tbs.uniqueId
join classification c on c.uniqueId = t.fkClassification
join classificationPrice cp on cp.fkClassification = c.uniqueId
join person p on p.uniqueId = tbs.fkPerson
WHERE convert(date, t.entryDate) = '6/20/2018'
and (convert(time, t.entryDate) >= convert(time, '12:00')
and convert(time, t.entryDate) <= convert(time, '15:00'))
and cp.entryDate = (SELECT MAX(entryDate)
from classificationPrice
where classificationPrice.fkClassification = c.uniqueId
and entryDate <= t.entryDate)
order by convert(time, t.entryDate)
I have attempted to do so here:
from t in context.Ticket
join c in context.Classification on t.FkClassification equals c.UniqueId
join cp in context.ClassificationPrice on c.UniqueId equals cp.FkClassification into cpc
let price = cpc.Where(f => f.FkClassification == c.UniqueId && f.EntryDate <= t.EntryDate).OrderByDescending(p => p.EntryDate).Take(1).FirstOrDefault().Price
join tbs in context.TollBoothShift on t.FkTollBoothShift equals tbs.UniqueId
join p in context.Person on tbs.FkPerson equals p.UniqueId
where t.EntryDate.Date == date.Date && (t.EntryDate.TimeOfDay >= startTime.TimeOfDay && t.EntryDate.TimeOfDay <= endTime.TimeOfDay) && t.Weight != null
orderby t.EntryDate.TimeOfDay
select
new WeighingLogReportModel
{
ticketNumber = t.UniqueId.ToString(),
entryDate = t.EntryDate,
entryTime = t.EntryDate.ToShortTimeString(),
tollBoothNumber = tbs.UniqueId.ToString(),
supervisor = "",
weight = t.Weight,
cost = price.ToString("N2"),
ownerDriver = string.Empty,
tollBoothShift = tbs.StartTime.ToShortTimeString() + " to " + tbs.EndTime.Value.ToShortTimeString() + "h",
licencePlatePrefix = t.LicencePlatePrefix,
licencePlateSuffix = t.LicencePlateSuffix
}
It seems, you missed the last condition in LINQ query
and cp.entryDate = (SELECT MAX(entryDate)
from classificationPrice
where classificationPrice.fkClassification = c.uniqueId
and entryDate <= t.entryDate)
You can covert this condition to LINQ and add it to existing where clause
cp.EntryDate == ClassificationPrice.Where(x=> x.FkClassification == c.UniqueId).Max(y=> y.EntryDate)
So your final where clause will be
where t.EntryDate.Date == date.Date
&& (t.EntryDate.TimeOfDay >= startTime.TimeOfDay
&& t.EntryDate.TimeOfDay <= endTime.TimeOfDay)
&& t.Weight != null
&& cp.EntryDate == ClassificationPrice.Where(x=> x.FkClassification == c.UniqueId).Max(y=> y.EntryDate)

How to Select new model list after GroupBy mothod in Linq?

I want select grouped rows to a new model list.this is my code:
List<Model_Bulk> q = (from a in db.Advertises
join c in db.Companies on a.AdvertiseCompanyID equals c.CompanyID
where a.AdvertiseActive == true
&& a.AdvertiseExpireDate.HasValue
&& a.AdvertiseExpireDate.Value > DateTime.Now
&& (a.AdvertiseObjectType == 1
|| a.AdvertiseObjectType == 2)
select c)
.GroupBy(a => a.CompanyID).Select(a => new Model_Bulk
{
CompanyEmail = a.CompanyContactInfo.Email,
CompanyID = a.CompanyID,
CompanyName = a.CompanyName,
Mobile = a.CompanyContactInfo.Cell,
UserEmail = a.User1.Email,
categories = a.ComapnyCategories
}).ToList();
After group by, i can not use Select and naturally this syntax error raised:
System.Linq.IGrouping' does not contain a definition for 'CompanyContactInfo' and no extension method 'CompanyContactInfo' accepting a first argument of type
System.Linq.IGrouping' could be found (are you missing a using directive or an assembly reference?)
If i try with SelectMany() method.but the result will repeated and groupby method not work properly:
List<Model_Bulk> q = (from a in db.Advertises
join c in db.Companies on a.AdvertiseCompanyID equals c.CompanyID
where a.AdvertiseActive == true
&& a.AdvertiseExpireDate.HasValue
&& a.AdvertiseExpireDate.Value > DateTime.Now
&& (a.AdvertiseObjectType == 1
|| a.AdvertiseObjectType == 2)
select c)
.GroupBy(a => a.CompanyID).SelectMany(a => a).Select(a => new Model_Bulk
{
CompanyEmail = a.CompanyContactInfo.Email,
CompanyID = a.CompanyID,
CompanyName = a.CompanyName,
Mobile = a.CompanyContactInfo.Cell,
UserEmail = a.User1.Email,
categories = a.ComapnyCategories
}).ToList();
Instead of .SelectMany(a => a) you can use .Select(g => g.First()).That will give you the first item of each group.
(from a in db.Advertises
join c in db.Companies on a.AdvertiseCompanyID equals c.CompanyID
where a.AdvertiseActive == true && a.AdvertiseExpireDate.HasValue && a.AdvertiseExpireDate.Value > DateTime.Now && (a.AdvertiseObjectType == 1 || a.AdvertiseObjectType == 2)
select c)
.GroupBy(a => a.CompanyID)
.Select(g => g.First())
.Select(a => new Model_Bulk
{
CompanyEmail = a.CompanyContactInfo.Email,
CompanyID = a.CompanyID,
CompanyName = a.CompanyName,
Mobile = a.CompanyContactInfo.Cell,
UserEmail = a.User1.Email,
categories = a.ComapnyCategories
}).ToList();
Note that this might not be supported, if that is the case add an AsEnumerable call before .Select(g => g.First())
You should understand that after you do GroupBy() in your LinQ expresstion you work with a group so in your example it will be good to write like this:
List<Model_Bulk> q =
(from a in db.Advertises join c in db.Companies on a.AdvertiseCompanyID equals c.CompanyID
where a.AdvertiseActive == true
&& a.AdvertiseExpireDate.HasValue
&& a.AdvertiseExpireDate.Value > DateTime.Now
&& (a.AdvertiseObjectType == 1 || a.AdvertiseObjectType == 2)
select c)
.GroupBy(a => a.CompanyID)
.Select(a => new Model_Bulk
{
CompanyEmail = a.First().CompanyContactInfo.Email,
CompanyID = a.Key, //Note this line, it's can be happened becouse of GroupBy()
CompanyName = a.First().CompanyName,
Mobile = a.First().CompanyContactInfo.Cell,
UserEmail = a.First().User1.Email,
categories = a.First().ComapnyCategories
}).ToList();
Instead you could try something like this, instead of mixing query expressions and methods... (using FirstOrDefault() in the where / select as necessary)
(from a in db.Advertises
join c in db.Companies on a.AdvertiseCompanyID equals c.CompanyID
group a by new { a.CompanyId } into resultsSet
where resultsSet.AdvertiseActive == true && resultsSet.AdvertiseExpireDate.HasValue && resultsSet.AdvertiseExpireDate.Value > DateTime.Now && (resultsSet.AdvertiseObjectType == 1 || resultsSet.AdvertiseObjectType == 2)
select new Model_Bulk
{
CompanyEmail = resultsSet.CompanyContactInfo.Email,
CompanyID = resultsSet.CompanyID,
CompanyName = resultsSet.CompanyName,
Mobile = resultsSet.CompanyContactInfo.Cell,
UserEmail = resultsSet.User1.Email,
categories = resultsSet.ComapnyCategories
}).ToList();

Categories

Resources