linq query, search by max date if previous date exists - linq

I'm trying to get three columns back from the database, DecalExpireDate, DecalExpireMonth and DecalExpireYear. Basically, I'm trying to check if it has a previous expiration date and if it does, I need to get the latest expiration date, as it may have multiple previous expiration dates.
var previousExpirationDate = (from d in db.CT_Decals
where d.TankID == decal.TankID
&& d.DecalStatus == "Approved"
&& d.DecalExpireDate == ((from dn in db.CT_Decals
where dn.TankID == decal.TankID
&& dn.DecalStatus == "Approved"
select dn.DecalExpireDate).Max())
select new
{
d.DecalExpireDate,
d.DecalExpireMonth,
d.DecalExpireYear
});
This query isn't working, can anybody see the problem? I'm searching by TankID, Status = approved and then I try to use the max expirationDate.

How about this
var result = db.CT_Decals.Where(o => o.TankId == decal.TankId && o.DecalStatus == "Approved")
.OrderByDescending(o => o.DecalExpireDate)
.Select(o => new { o.DecalExpireDate,
o.DecalExireMonth,
o.DecalExireYear }).First()
or
var result = (from d in db.CT_Decals
where d.TankID == 1 && d.Status == "Approved"
orderby d.ExpireDate descending
select new { d.DecalExpireDate,
d.DecalExpireMonth,
d.ExpireDate }).First();

The problem it's with the that max function couldn't be translated to Sql in the scope that you need so you could try like this
var previousExpirationDate = (from d in db.CT_Decals
where d.TankID == decal.TankID
&& d.DecalStatus == "Approved"
&& d.DecalExpireDate == ((from dn in db.CT_Decals
where dn.TankID == decal.TankID
&& dn.DecalStatus == "Approved"
order by dn.DecalExpireDate
select dn.DecalExpireDate).First())
select new
{
d.DecalExpireDate,
d.DecalExpireMonth,
d.DecalExpireYear
});

Although Max may be the problem in your example, it would be nice to find a way to use it properly because it is faster than sorting. How about:
Edit: this answer only returns the DecalExpireDate
var previousExpirationDate = (from d in db.CT_Decals
where d.TankID == decal.TankID
&& d.DecalStatus == "Approved"
select new
{
d.DecalExpireDate,
d.DecalExpireMonth,
d.DecalExpireYear
}).Max(d => d.DecalExpireDate);
For this version you will have to test to see if it's worth making an extra call to the database to avoid sorting:
var latestDate = (from d in db.CT_Decals
where d.TankID == decal.TankID
&& d.DecalStatus == "Approved"
select d.DecalExpireDate).Max();
var previousExpirationDate = (from d in db.CT_Decals
where d.TankID == decal.TankID
&& d.DecalStatus == "Approved"
&& d.DecalExpireDate == latestDate
select new
{
d.DecalExpireDate,
d.DecalExpireMonth,
d.DecalExpireYear
}).First();

Related

Is there anyway to return int and null with nested conditions?

I want to return a customer which is in this city and buy ItemID = 1, 2 or NULL
List<int?> AcceptableValues = new List<int?>
{
1,2
};
List<Customer> Customers = ListOfCustomer.Where(x => x.CountryTbl.City == 1
&& x.ItemTbl.Any(p => p.ItemID == 1 || p.ItemID ==2 || p.Item is null)
&& x.SellTbl.SellType == 10).ToList();
Is there any way we can use LINQ to filter the customer who only buys itemID in the AcceptableValues ?
I've tried with ItemTbl.SingleOrDefault, or ItemTbl.Where, or AppeptableValues.Contains(m => m.ItemID) but didn't work.
List<Customer> Customers = ListOfCustomer
.Where(c => c.CountryTbl.City == 1
&& c.ItemTbl.Any(i => i.ItemID == null || AcceptableValues.Contains(i.ItemID))
&& c.SellTbl.SellType == 10).ToList();

C#: LINQ not returning the same result as SQL

I'm trying to convert the following SQL query to LINQ, but getting different result count with both,
SQL Query:
SELECT T5.CNTR, T5.BenefitCode,T5.ApprovedFlag,
T5.PaymentFrequencyCode, T5.InstalmentAmt, T5.TotalAmt,
T5.CarRego
FROM
dbo.EmployeeBenefit As T5
LEFT JOIN dbo.Payee ON T5.PayeeCntr = dbo.Payee.CNTR
LEFT JOIN dbo.BankDetails ON dbo.Payee.BankCntr = dbo.BankDetails.BankCntr
Left Join dbo.EmployeeCar As T4 on T5.EmployeeCarCntr=T4.Cntr
Inner Join dbo.EmployeeEntity As T1 On T5.EmployeeEntityCntr=T1.EmployeeEntityCntr
Inner Join dbo.EmployerEntity As T2 On T1.EmployerEntityCntr=T2.EmployerEntityCntr
where T5.EmployeeCntr = 117165
AND ((T5.EndDate is Null) OR (T5.EndDate >= GETDATE()))
LINQ:
var result = (from employeeBenefit in context.EmployeeBenefit
from payee in context.Payee.Where(x => x.Cntr == employeeBenefit.PayeeCntr).DefaultIfEmpty()
from bankDetails in context.BankDetails.Where(x => x.BankCntr == employeeBenefit.PayeeCntr).DefaultIfEmpty()
from employeeCar in context.EmployeeCar.Where(x => x.Cntr == payee.BankCntr).DefaultIfEmpty()
from employeeEntity in context.EmployeeEntity
where employeeEntity.EmployeeEntityCntr == employeeBenefit.EmployeeEntityCntr
from employeeEntity1 in context.EmployeeEntity
where employeeEntity.EmployerEntityCntr == employeeEntity1.EmployerEntityCntr
&& employeeBenefit.EmployeeCntr == iEmployeeID
&& (!employeeBenefit.EndDate.HasValue || employeeBenefit.EndDate >= DateTime.Now)
&& employeeBenefit.EmployeeCntr == 117165
&& employeeBenefit.CarRego == registration
select new
{
CNTR = employeeBenefit.Cntr,
BenefitCode = employeeBenefit.BenefitCode,
PaymentFrequencyCode = employeeBenefit.PaymentFrequencyCode,
InstalmentAmount = employeeBenefit.InstalmentAmt,
TotalAmount = employeeBenefit.TotalAmt,
CarRego = employeeBenefit.CarRego,
ApprovedFlag = employeeBenefit.ApprovedFlag
}).ToList();
Please let me know what i'm missing.
For the data in my database the SQL query is returning 10 records. But, the LINQ is returning 2700 records.
Not a full answer (I'm late for work) but:
var result = (from T5 in context.EmployeeBenefit
join PY in dbo.Payee on T5.PayeeCntr equals PY.CNTR into PY1
where T5.EmployeeCntr = 117165
select new {
CNTR = T5.Cntr,
...
}
).ToList();
It was the issue with the condition mismatch that i had done in the LINQ. The below query just worked fine. Thank you for helping me with the issue.
var result = (from employeeBenefit in context.EmployeeBenefit
from payee in context.Payee.Where(x => x.Cntr == employeeBenefit.PayeeCntr).DefaultIfEmpty()
from bankDetails in context.BankDetails.Where(x => x.BankCntr == payee.BankCntr).DefaultIfEmpty()
from employeeCar in context.EmployeeCar.Where(x => x.Cntr == employeeBenefit.EmployeeCarCntr).DefaultIfEmpty()
join employeeEntity in context.EmployeeEntity
on employeeBenefit.EmployeeEntityCntr equals employeeEntity.EmployeeEntityCntr
join employerEntity in context.EmployerEntity
on employeeEntity.EmployerEntityCntr equals employerEntity.EmployerEntityCntr
where employeeBenefit.EmployeeCntr == 117165 && (!employeeBenefit.EndDate.HasValue || employeeBenefit.EndDate >= DateTime.Now)
select new
{
CNTR = employeeBenefit.Cntr,
BenefitCode = employeeBenefit.BenefitCode,
PaymentFrequencyCode = employeeBenefit.PaymentFrequencyCode,
InstalmentAmount = employeeBenefit.InstalmentAmt,
TotalAmount = employeeBenefit.TotalAmt,
CarRego = employeeBenefit.CarRego,
ApprovedFlag = employeeBenefit.ApprovedFlag
}).ToList();

LINQ with Lambda Expressions

How can I convert the LINQ query below using LAMBDA Expressions ?
var select = from si in db.San_Imovel
join sic in db.San_Imovel_caracteristica
on si.Imovel_Id equals Convert.ToInt64(sic.Imovel_Id)
join sf in db.San_Filial
on si.Credenciada_Id equals sf.Credenciada_Id
where si.Credenciada_Id == credenciada_Id
&& (si.GrupoImovel_Id.ToString().Contains("1") || si.GrupoImovel_Id.ToString().Contains("2"))
&& (si.Status_Id.ToString().Contains("1") || si.Status_Id.ToString().Contains("12"))
&& si.NomeArquivo != null
&& (si.Imovel_Id.ToString().Contains(""))
select new
{
si.Celula_Id,
si.Credenciada_Id,
si.Imovel_Id,
si.NomeArquivo,
si.TipoDsc1,
si.BairroDsc1,
si.AreaRealPrivativa,
sic.VagasGaragem,
si.ValorImovel,
si.ValorCondominio,
si.ValorIPTU,
si.Lat2,
si.Lon2,
sf.ApelidoCredenciada,
sf.ddd,
sf.TelefoneVenda,
sf.TelefoneLocacao,
sf.Email,
si.Bairro1,
si.NomeCidade,
si.Transacao_ID
};
var query =
db.San_Imovel
.Join(db.San_Imovel_caracteristica,
si => Imovel_Id,
sic => Convert.ToInt64(sic.Imovel_Id),
(si, sic) => new { si, sic })
.Join(db.San_Filial,
x => x.si.Credenciada_Id,
sf => sf.Credenciada_Id,
(x, sf) => new { x.si, x.sic, sf })
.Where(x => x.si.Credenciada_Id == credenciada_Id &&
(x.si.GrupoImovel_Id.ToString().Contains("1") ||
x.si.GrupoImovel_Id.ToString().Contains("2")) &&
(x.si.Status_Id.ToString().Contains("1") ||
x.si.Status_Id.ToString().Contains("12")) &&
x.si.NomeArquivo != null &&
(x.si.Imovel_Id.ToString().Contains(""))
.Select(x => new {
x.si.Celula_Id,
x.si.Credenciada_Id,
x.si.Imovel_Id,
x.si.NomeArquivo,
x.si.TipoDsc1,
x.si.BairroDsc1,
x.si.AreaRealPrivativa,
x.sic.VagasGaragem,
x.si.ValorImovel,
x.si.ValorCondominio,
x.si.ValorIPTU,
x.si.Lat2,
x.si.Lon2,
x.sf.ApelidoCredenciada,
x.sf.ddd,
x.sf.TelefoneVenda,
x.sf.TelefoneLocacao,
x.sf.Email,
x.si.Bairro1,
x.si.NomeCidade,
x.si.Transacao_ID
});
BTW you don't need to convert whole query to method syntax. You can convert only filtering where part.

Linq join with exists

I'm busy rewriting a system and are using Linq queries to extract data from the database. I am used to plain old TSQL and stored procedures so my Linq skills are not the best.
I have a sql query that I try to rewrite in Linq that contains a join, where clause and IN statements. I do get it right but when I run the sql query I get a different value as from the Linq query. Somewhere I'm missing something and can't find the reason.
Here is the SQL:
select
isnull(Sum(QtyCC) + Sum(QtyEmployee), 0) *
isnull(Sum(UnitPrice), 0)[TotalRValue]
from
tbl_app_KGCWIssueLines a
inner join tbl_app_KGCWIssue b on b.IssueNrLnk = a.IssueNrLnk
where
b.CreationDate >= '2011-02-01' and
a.IssueNrLnk IN (
select
IssueNrLnk
from
tbl_app_KGCWIssue
where
CustomerCode = 'PRO002' and
ISNULL(Tier1,'') = 'PRO002' and
ISNULL(Tier2,'') = 'HAMD01' and
ISNULL(Tier3,'') = '02' and
ISNULL(Tier4,'') = '02001' and
ISNULL(Tier5,'') = 'PTAHQ001' and
ISNULL(Tier6,'') = '035' and
ISNULL(Tier7,'') = '' and
ISNULL(Tier8,'') = '' and
ISNULL(Tier9,'') = '' and
ISNULL(Tier10,'') = ''
)
And here is the Linq:
ctx.ObjectContext.tbl_app_KGCWIssue
.Join(ctx.ObjectContext.tbl_app_KGCWIssueLines,
i => i.IssueNrLnk, l => l.IssueNrLnk, (i, l) => new { i, l })
.Where(o => o.i.CreationDate >= IntervalStartDate)
.Where(p => ctx.ObjectContext.tbl_app_KGCWIssue
.Where(a =>
a.CustomerCode == CustomerCode &&
a.Tier1 == employee.Tier1 &&
a.Tier2 == employee.Tier2 &&
a.Tier3 == employee.Tier3 &&
a.Tier4 == employee.Tier4 &&
a.Tier5 == employee.Tier5 &&
a.Tier6 == employee.Tier6 &&
a.Tier7 == employee.Tier7 &&
a.Tier8 == employee.Tier8 &&
a.Tier9 == employee.Tier9 &&
a.Tier10 == employee.Tier10)
.Select(i => i.IssueNrLnk)
.Contains(p.l.IssueNrLnk))
.Sum(p => p.l.UnitPrice * (p.l.QtyEmployee + p.l.QtyCC));

LINQ Join Errors

I'm getting the following error:
The type of one of the expressions in the join clause is incorrect. Type inference failed in the call to 'Join'.
when using the code below
var ccrCodes = (from c in db.CCRCodes
join i in items on
new { c.baan_cat_fam_code, c.baan_cat_code } equals
new { i.baan_cat_family_code, i.baan_cat_code }
where i => i.contact_dt.Value.Year == date.Year && i.contact_dt.Value.Month == date.Month
select c).Distinct().OrderBy(c => c.code_desc);
What I'm trying to do in LINQ is create a multi-condition join and am running into problems. Any ideas?
Thanks,
Try giving names to the properties in your anonymous objects:
var ccrCodes = (from c in db.CCRCodes
join i in items on
new { FamCode = c.baan_cat_fam_code, CatCode = c.baan_cat_code } equals
new { FamCode = i.baan_cat_family_code, CatCode = i.baan_cat_code }
where i => i.contact_dt.Value.Year == date.Year && i.contact_dt.Value.Month == date.Month
select c).Distinct().OrderBy(c => c.code_desc);
EDIT: Alright, I have to confess, I am no expert on query syntax, but you want to filter the 'items' list before doing the join, like the following fluent version of your query:
db.CCRCodes
.Join(
items.Where(i => i.contact_dt.Value.Year == date.Year && i.contact_dt.Value.Month == date.Month),
x => new { FamCode = x.baan_cat_fam_code, CatCode = x.baan_cat_code },
x => new { FamCode = x.baan_cat_family_code, CatCode = x.baan_cat_code },
(o,i) => o
).Distinct().OrderBy(c => c.code_desc)
ANOTHER EDIT: Per Ahmad's suggestion:
var ccrCodes = (from c in db.CCRCodes
join i in items.Where(x => x.contact_dt.Value.Year == date.Year && x.contact_dt.Value.Month == date.Month) on
new { FamCode = c.baan_cat_fam_code, CatCode = c.baan_cat_code } equals
new { FamCode = i.baan_cat_family_code, CatCode = i.baan_cat_code }
select c).Distinct().OrderBy(c => c.code_desc);
YET ANOTHER EDIT: Per another Ahmad suggestion:
var ccrCodes = (from c in db.CCRCodes
from i in items
where i.contact_dt.Value.Year == date.Year && i.contact_dt.Value.Month == date.Month
&& c.baan_cat_fam_code == i.baan_cat_family_code && c.baan_cat_code == i.baan_cat_code
select c).Distinct().OrderBy(c => c.code_desc);

Resources