Select SQL case when for Entity Framework - entity-framework

I have this select which works in T-SQL, but need to convert to Entity Framework. How can I use case in Entity Framework?
select
*
from
Contrato c
where
c.QtdParcelasFalta > 0
and (case
when c.DiaEspecificoMarcar = 1
then c.DiaEspecifico
when c.DiaEspecificoMarcar = 0
then (select convert(int, substring(DataCobranca, 2, 2))
from Contrato
where Contrato.Id = c.Id) -
(select e.DataProcessamentoNota
from Contrato t
inner join PedidoVenda p on p.id = t.PedidoVendaId
inner join Empresas e on p.EmpresaID = e.Id
where p.id = t.PedidoVendaId
and t.id = c.Id and p.EmpresaID = 1)
end) = (SELECT DAY(GETDATE()))
I tried it like this, but it didn't work out, did not pass the correct values, because I'm not aware of pass to Entity Framework:
var contrato = db.Contrato
.Include(a => a.PedidoVenda)
.Include(a => a.Cliente)
.Where(a => a.PedidoVenda.EmpresaID == model.EmpresaID
&& a.Cancelado == false
&& a.DiaEspecificoMarcar == true
&& a.DiaEspecifico == int.Parse(DateTime.Now.ToString("dd")) ||
(int.Parse(a.DataCobranca.Substring(1, 2)) - a.PedidoVenda.Empresa.DataProcessamentoNota)
== int.Parse(DateTime.Now.ToString("dd"))
).ToList();

You are actually on the right track. You just need to add when conditions to your lef and right conditions like this:
var contrato = db.Contrato.Include(a => a.PedidoVenda).Include(a => a.Cliente).Where
(a => a.PedidoVenda.EmpresaID == model.EmpresaID && a.Cancelado == false &&
a.DiaEspecificoMarcar == false && a.DiaEspecifico == int.Parse(DateTime.Now.ToString("dd")) ||
( a.DiaEspecificoMarcar == true && int.Parse(a.DataCobranca.Substring(1, 2)) - a.PedidoVenda.Empresa.DataProcessamentoNota)
== int.Parse(DateTime.Now.ToString("dd"))
).ToList();
I also suggest you use DateTime.Now from a variable to be sure both int.Parse gets the same input

Related

How do you use aggregate functions in LINQ?

I can do this really easily in SQL but I can't translate it into LINQ.
The SQL:
SELECT EmployeeId
,YEAR(DistributionDate) AS DistributionYear
,SUM(SalesLocal * FX.ExchangeRate) AS TotalDistributions
FROM Distributions AS DD INNER JOIN FiscalPeriod AS FP ON DD.DistributionDate BETWEEN FP.StartDate AND FP.EndDate
INNER JOIN FXRates AS FX ON FP.FiscalPeriodId = FX.FiscalPeriodId AND FX.FromCurrencyId = DD.CurrencyId AND FX.ToCurrencyId = 'USD'
GROUP BY EmployeeId, YEAR(DistributionDate)
ORDER BY EmployeeId, DistributionYear
This is my broken attempt at translation:
var pointList = (from dd in db.Distributions
join e in db.Employee on dd.EmployeeId equals e.EmployeeId
join fp in db.FiscalPeriod.Where(p => dd.DistributionDate >= p.StartDate && dd.DistributionDate <= p.EndDate)
join fx in db.Fxrates on (fp.FiscalPeriodId equals fx.FiscalPeriodId) && (fx.FromCurrencyId equals dd.CurrencyId) && (fx.ToCurrencyId equals "USD")
group by dd.EmployeeId && dd.DistributionDate.Year
select new Point<int, decimal?>
{
X = dd.DistributionDate.Year,
Y = dd.Sum(dd.SalesLocal * fx.ExchangeRate)
}).ToList();
Visual Studio complains first that dd is not declared and then really complains once it reaches the join to Fxrates.
I think this may be close to what you want:
var pointList = (from dd in db.Distributions
join e in db.Employee on dd.EmployeeId equals e.EmployeeId
from fp in db.FiscalPeriod.Where(p => dd.DistributionDate >= p.StartDate && dd.DistributionDate <= p.EndDate)
from fx in db.Fxrates.Where(fx2 => fp.FiscalPeriodId == fx2.FiscalPeriodId && fx2.FromCurrencyId == dd.CurrencyId && fx2.ToCurrencyId == "USD")
group new { dd, fx } by new { dd.EmployeeId, dd.DistributionDate.Year } into distGroup
select new
{
X = distGroup.Key.Year,
Y = distGroup.Sum(d => d.dd.SalesLocal * d.fx.ExchangeRate)
}).ToList();

Increase EF query performance

I currently have the following code in my project
public List<PermissionValue> GetUnderlyingPermissionsForUser(string userName, int guiPermissionTypeId, int productTypeId)
{
using (CliVeEntities db = new CliVeEntities())
{
var listUnderlyings = (from gui in db.GuiPermissionUnderlying
join bue in db.BranchUsersExternal on gui.BranchUsersId equals bue.BranchUsersID
join bu in db.BranchUsers on bue.BranchUsersID equals bu.BranchUsersId
where bu.UserName == userName && gui.ViewTypeId == guiPermissionTypeId
&& gui.UnderlyingId.HasValue
&& !gui.SectorId.HasValue
&& gui.ProductTypeId == null
&& gui.ProductGroupId == null
select new PermissionValue { Id = gui.UnderlyingId.Value, Visible = gui.value}).ToList<PermissionValue>();
var listUnderlyingsProductGroup = (from gui in db.GuiPermissionUnderlying
join bue in db.BranchUsersExternal on gui.BranchUsersId equals bue.BranchUsersID
join bu in db.BranchUsers on bue.BranchUsersID equals bu.BranchUsersId
join pg in db.ProductGroup on gui.ProductGroupId equals pg.ProductGroupId
join pt in db.ProductType on pg.ProductGroupId equals pt.ProductGroupId
where bu.UserName == userName && gui.ViewTypeId == guiPermissionTypeId
&& gui.UnderlyingId.HasValue
&& !gui.SectorId.HasValue
&& pt.ProductTypeId == productTypeId
select new PermissionValue { Id = gui.UnderlyingId.Value, Visible = gui.value }).ToList<PermissionValue>();
var listUnderlyingsProductType = (from gui in db.GuiPermissionUnderlying
join bue in db.BranchUsersExternal on gui.BranchUsersId equals bue.BranchUsersID
join bu in db.BranchUsers on bue.BranchUsersID equals bu.BranchUsersId
where bu.UserName == userName && gui.ViewTypeId == guiPermissionTypeId
&& gui.UnderlyingId.HasValue
&& !gui.SectorId.HasValue
&& gui.ProductTypeId == productTypeId
select new PermissionValue { Id = gui.UnderlyingId.Value, Visible = gui.value }).ToList<PermissionValue>();
var listUnderlyingsForSectors = (from gui in db.GuiPermissionUnderlying
join bue in db.BranchUsersExternal on gui.BranchUsersId equals bue.BranchUsersID
join bu in db.BranchUsers on bue.BranchUsersID equals bu.BranchUsersId
join u in db.Underlying on gui.SectorId equals u.SectorId
where bu.UserName == userName && gui.ViewTypeId == guiPermissionTypeId
&& !gui.UnderlyingId.HasValue
&& gui.ProductTypeId == null
&& gui.ProductGroupId == null
select new PermissionValue { Id = u.UnderlyingId, Visible = gui.value }).ToList<PermissionValue>();
var listUnderlyingsForSectorsProductGroup = (from gui in db.GuiPermissionUnderlying
join bue in db.BranchUsersExternal on gui.BranchUsersId equals bue.BranchUsersID
join bu in db.BranchUsers on bue.BranchUsersID equals bu.BranchUsersId
join u in db.Underlying on gui.SectorId equals u.SectorId
join pg in db.ProductGroup on gui.ProductGroupId equals pg.ProductGroupId
join pt in db.ProductType on pg.ProductGroupId equals pt.ProductGroupId
where bu.UserName == userName && gui.ViewTypeId == guiPermissionTypeId
&& !gui.UnderlyingId.HasValue
&& pt.ProductTypeId == productTypeId
select new PermissionValue { Id = u.UnderlyingId, Visible = gui.value }).ToList<PermissionValue>();
var listUnderlyingsForSectorsProductType = (
from gui in db.GuiPermissionUnderlying
join bue in db.BranchUsersExternal on gui.BranchUsersId equals bue.BranchUsersID
join bu in db.BranchUsers on bue.BranchUsersID equals bu.BranchUsersId
where bu.UserName == userName && gui.ViewTypeId == guiPermissionTypeId
&& !gui.UnderlyingId.HasValue
&& gui.SectorId.HasValue
&& gui.ProductTypeId == productTypeId
select new PermissionValue { Id = gui.UnderlyingId.Value, Visible = gui.value }).ToList<PermissionValue>();
var mergeList1 = MergeAndDistinctList(listUnderlyings, listUnderlyingsProductType);
var mergeList2 = MergeAndDistinctList(mergeList1, listUnderlyingsProductGroup);
var mergeList3 = MergeAndDistinctList(mergeList2, listUnderlyingsForSectors);
var mergeList4 = MergeAndDistinctList(mergeList3, listUnderlyingsForSectorsProductType);
var resultMergeList = MergeAndDistinctList(mergeList4, listUnderlyingsForSectorsProductGroup);
return resultMergeList;
And This is the code for my MergeAndDistinctList function
protected List<PermissionValue> MergeAndDistinctList(List<PermissionValue> listPrimary, List<PermissionValue> listSecondry)
{
List<PermissionValue> listMergedAndDistinct = new List<PermissionValue>();
listMergedAndDistinct.AddRange(listPrimary);
var filter = listPrimary.Select<PermissionValue, int>(p => p.Id);
listMergedAndDistinct.AddRange(listSecondry.Where<PermissionValue>(p => !filter.Contains(p.Id)).Select(p => p));
return listMergedAndDistinct;
}
My problem with my GetUnderlyingsForClient() code is that it hits the database multiple times. If this method gets hit quite a lot then this could translate to multiple calls to the database.
Does anybody know of any ways to make this code more efficient and reduce the amount of DB calls i have to make.
It seems that you make a lot of queries on the same table (a in your case)
To limit database queries, you can get all data needed in a local list and use this list for your multiple queries like this :
var MyBaseList = db.A.ToList();
var listUnderlyings = (from a MyBaseList [...]
var listUnderlyingsProductGroup = (from a MyBaseList [...]
And for limit the data retrieval, filter MyBaseList to get only lines used by following queries.
You could Union your queries following this simplified pattern:
(from a in As where a.Id > 0 select a)
.Union(
from a in As where a.Name == "a" select a)
.Union(
...
)
.Select(a => new { a.x, a.y })
.Distinct()
The Union is the merge part of your MergeAndDistinctList and the Distinct, ehh, the distinct part. The nice thing is: the Distinct is carried out over the projection (Id and Visible in your case).
Everything should be carried out in one (monster) query now, without the intermediate forced execution that is caused by the AddRange in MergeAndDistinctList.
Looking at your queries I have a feeling that you could do with a smaller number of them by combining some conditions, but that's up to you.

LINQ to Entities: Convert SQL Sub Select

I got this figured out.
No need to answer.
The system says I have to wait 8 hours before answering my own questions. But for now the answer is below:
Here is the answer:
var startDate = DateTime.Today.AddDays(-30);
var results = (from h in Histories
join q in Quotes
on h.QuoteID equals q.QuoteID
join a in Agencies
on q.AgencyID equals a.AgencyID
where q.Status == "Inforce" &&
q.LOB == "Vacant" &&
q.EffectiveDate > startDate &&
h.Deleted == null &&
h.DeprecatedBy == null &&
h.TransactionStatus == "Committed" &&
a.DC_PLT_Roles.Any(r => r.Name == "Wholesaler")
group new {h} by new {h.PolicyNumber} into g
select new {
MaxHistoryID = g.Max (x => x.h.HistoryID),
comment = (from h2 in Histories
where h2.HistoryID == g.Max (x => x.h.HistoryID)
select h2.Comment).FirstOrDefault()
}).ToList();
The key code was:
comment = (from h2 in Histories
where h2.HistoryID == g.Max (x => x.h.HistoryID)
select h2.Comment).FirstOrDefault()
We are in the process of converting SQL / Stored Procedures to LINQ to Entities statements. And I can’t figure out the proper syntax for a sub select.
Currently I am converting this SQL:
declare #startDate DateTime
set #startDate = DATEADD(DD, -30, GETDATE())
select * from history where historyid in(
select MAX(h.historyid) as HistoryId
from History h (nolock)
inner join Quote q (nolock) on h.QuoteID = q.QuoteID
inner join Agency (nolock) a on q.AgencyID = a.AgencyID
inner join DC_PLT_EntityRoles er (nolock) on a.AgencyID = er.EntityID
inner join DC_PLT_Roles (nolock) r on er.RoleID = r.RoleID
where
q.Status = 'Inforce'
and q.LOB = 'Vacant'
and q.EffectiveDate > #startDate
and h.Deleted is null --
and h.DeprecatedBy is null --
and h.TransactionStatus = 'Committed'
and r.Name = 'Wholesaler'
group by h.PolicyNumber)
As you can see the code above is made up of two select statements. The main select (select * from history).. And a filter select (select MAX(h.historyid)…)
I got the filter select working (See below):
var startDate = DateTime.Today.AddDays(-30);
var results = (from h in Histories
join q in Quotes
on h.QuoteID equals q.QuoteID
join a in Agencies
on q.AgencyID equals a.AgencyID
where q.Status == "Inforce" &&
q.LOB == "Vacant" &&
q.EffectiveDate > startDate &&
h.Deleted == null &&
h.DeprecatedBy == null &&
h.TransactionStatus == "Committed" &&
a.DC_PLT_Roles.Any(r => r.Name == "Wholesaler")
group new {h} by new {h.PolicyNumber} into g
select new {
MaxHistoryID = g.Max (x => x.h.HistoryID)
}).ToList();
However I can’t figure out the proper syntax to set up the main select. (Basically getting the records from the History table using the HistoryID from the filter select.)
Any help would be appreciated.
Thanks for your help.
I figured it out, here is the code:
var startDate = DateTime.Today.AddDays(-30);
var results = (from h in Histories
.Include("Quote")
.Include("Quote.Agency")
where h.Quote.Status == "Inforce" &&
h.Quote.LOB == "Vacant" &&
h.Quote.EffectiveDate > startDate &&
h.Deleted == null &&
h.DeprecatedBy == null &&
h.TransactionStatus == "Committed" &&
h.Quote.Agency.DC_PLT_Roles.Any(r => r.Name == "Wholesaler")
group new {h} by new {h.PolicyNumber} into g
select new {
XMLData = (from h2 in Histories
where h2.HistoryID == g.Max (x => x.h.HistoryID)
select h2.XMLData).FirstOrDefault()
}).ToList();
The key logic is:
select new {
XMLData = (from h2 in Histories
where h2.HistoryID == g.Max (x => x.h.HistoryID)
select h2.XMLData).FirstOrDefault()
}).ToList();
Gotta love the Nested Query

SQL "WHERE IN" query conversion to LINQ

I'm trying to find a way to convert this very complex SQL Query into LINQ and I can't seem to tackle all the embedded "WHERE IN" clauses. Would someone be so kind as to lend me a helping hand?
Here is the SQL code (don't worry about the stored procedure, it's a count of a row total)
SELECT
(SELECT pac.Name FROM Account pac WHERE pac.AccountID = AC.ParentAccountID) AS ParentAccountName,
ac.Name, dv.DeviceID, dv.Manufacturer, dv.Model, dv.SerialNr, dv.PrinterIPAddress,
(SELECT TOP 1 au.AuditDate FROM PrinterAudit pa WITH (NOLOCK) INNER JOIN Audit au ON au.AuditID = pa.AuditID
WHERE pa.DeviceID=dv.DeviceID
ORDER BY AuditDate DESC) AS AuditDate,
dbo.Get_TotalPageCountByDeviceId( DATEADD(month, -3, GETDATE()), GETDATE(), dv.DeviceID ) as TotalUsageLast3Months
FROM Account ac WITH (NOLOCK)
INNER JOIN Device dv ON ac.AccountID = dv.AccountID
WHERE dv.AccountID IN
( SELECT au.AccountID FROM Audit au WHERE au.AuditDate >= DATEADD(month, -3, GETDATE()) )
AND (dv.Manufacturer + dv.Model) IN
(SELECT (dv2.Manufacturer + dv2.Model)
FROM Device dv2
WHERE dv2.AccountID = dv.AccountID
AND dv2.Manufacturer = dv.Manufacturer
AND dv2.Model = dv.Model
AND (dv2.ERPEquipID IS NOT NULL OR dv2.ERPData IS NOT NULL ) )
AND dv.ERPEquipID IS NULL AND dv.ERPData IS NULL
AND dv.DeviceID IN
(SELECT pa.DeviceID
FROM PrinterAudit pa WITH (NOLOCK)
INNER JOIN Audit au ON au.AuditID = pa.AuditID
WHERE au.AuditDate >= DATEADD(month, -3, GETDATE()))
ORDER BY ParentAccountName, ac.Name
Final Result:
var result =
(from dv in Device
where Audit.Any(au => au.AuditDate >= DateTime.Now.AddMonths(-3)
&& au.AccountID == dv.AccountID)
where Device.Any(dv2 => dv2.AccountID == dv.AccountID
&& dv2.Manufacturer == dv.Manufacturer
&& dv2.Model == dv.Model
&& (dv2.ERPEquipID != null || dv2.ERPData != null)
&& dv.ERPEquipID == null
&& dv.ERPData == null
&& PrinterAudit.Any(pa => pa.Audit.AuditDate >= DateTime.Now.AddMonths(-3) && pa.DeviceID == dv.DeviceID))
orderby dv.Account.ParentAccountID, dv.Account.Name
select new
{
ParentAccountName = Account.Where(pac => pac.AccountID == dv.Account.ParentAccountID).Select(pac => pac.Name),
Name = dv.Account.Name,
DeviceID = dv.DeviceID,
Manufacturer = dv.Manufacturer,
Model = dv.Model,
SerialNumber = dv.SerialNr,
PrinterIPAddress = dv.PrinterIPAddress,
AuditDate = (from pa in PrinterAudit where pa.DeviceID == dv.DeviceID orderby pa.Audit.AuditDate descending select pa.Audit.AuditDate).Take(1),
TotalUsageLast3Months = (from p in PrinterAudit
where p.DeviceID == dv.DeviceID
group p by p.DeviceID into total
select new
{
Total = Get_TotalPageCountByDeviceId(DateTime.Now.AddMonths(-3), DateTime.Now, dv.DeviceID)
})
});
You convert the SQL IN statement to linq with either Contains or Any
Contains
from dv in db.Device
where
(from au in db.Audit
where au.AuditDate >= DateTime.Now.AddMonths(-3)
select au.AccountID).Contains(dv.AccountID)
Any
from dv in db.Device
where
db.Audit.Any(au => au.AuditDate >= DateTime.Now.AddMonths(-3) &&
au.AccountID == dv.AccountID)

NHibernate query help needed

Is it possible to convert the following query into ICriteria or LINQ, and if so, how?
SELECT Test.personid
FROM
(
SELECT r.PersonId AS personid, e.ActivityId
FROM Event e
INNER JOIN Registration r ON e.Id = r.EventId
WHERE e.ActivityId IN (1, 2)
GROUP BY r.PersonId, e.ActivityId
) AS Test
GROUP BY Test.personid
HAVING COUNT(Test.ActivityId) >= 2
var result = from r in session.Query<Registration>()
where r.Event.ActivityId == 1 || r.Event.ActivityId == 2
group r by r.Person into g
where g.Min(x => x.Event.ActivityId) != g.Max(x => x.Event.ActivityId)
select g.Key
the following states, take all Persons wich have different activityIds in there groups which is equivalent to
ActivityId == 1 || ActivityId == 2
Having Count(r.Event.ActivityId) >= 2