How to write Linq query from Sql query - c#

Can anyone please guide me on how I can write the LINQ for below SQL query
DECLARE #now DATETIME = dbo.GetInstanceDate(NULL);
select *
FROM [dbo].[creatives] AS [t0]
INNER JOIN [dbo].[contracts] AS [t1] ON [t0].[campaign_id] = [t1].[campaign_id]
LEFT OUTER JOIN [dbo].[vouchers] AS [t2] ON ([t1].[contract_id] = ([t2].[contract_id])) AND t0.creative_id = t2.creative_id
AND ([t2].[contract_id] = 29980)
AND (NOT ([t2].[removed] = 1))
AND ([t2].[active] = 1)
AND ((NOT ([t2].[start_date] IS NOT NULL)) OR (([t2].[start_date]) <= #now)) AND ((NOT ([t2].[expiration_date] IS NOT NULL)) OR (([t2].[expiration_date]) > #now))
AND (NOT ([t2].[creative_id] IS NOT NULL))
where [t1].contract_id = 29980

If you are looking for how to convert LEFT JOIN with complex filter there is simple way:
var query =
from t in context.Table
from o in context.OtherTable
.Where(o => o.id == t.Id && (o.Some == t.Some || o.Another == t.Another))
.DefaultIfEmpty()
select new { t, o };

Related

Join multiple columns from the same table using Linq

I would like to convert following sql query into Linq to SQL
select distinct r.CompanyLogo, j.JobName, j.JobId, ur.UserId, r.JobSeekerID
, ur.FirstName, j.JobType, j.JobCareerLevel, j.JobLocation
from UserInterest m
join job j on m.FunctionalId = j.FunctionId or m.Careerlevel = j.CarrerLevelId or m.SalId = j.SalaryRangeId
join UserRegistration ur on j.UserId = ur.UserId
join EmplrRegistration r on j.UserId = r.JobSeekerID
where m.Status = 1 and m.UserId = 1
going through this I have so far tried following which didn't work out
var list = (from m in entities.UserInterests
from j in entities.Jobs
where m.FunctionalId == j.FunctionId || m.SalId == j.SalaryRangeId || m.Careerlevel == j.CarrerLevelId
&& m.Status == true && m.UserId == 1
join ur in entities.UserRegistrations on m.UserId equals ur.UserId
join r in entities.EmplrRegistrations on m.UserId equals r.JobSeekerID
select new { r.CompanyLogo, j.JobName, j.JobId, ur.UserId, r.JobSeekerID
, ur.FirstName, j.JobType, j.JobCareerLevel, j.JobLocation }).Distinct().ToList();
Edit:
following query is being generated against Svyatoslav Danyliv answer which is returning 7 rows instead of 6
SELECT 1 AS [C1], [Extent4].[CompanyLogo] AS [CompanyLogo], [Extent2].[JobName] AS [JobName]
,[Extent2].[JobId] AS [JobId], [Extent3].[UserId] AS [UserId]
,[Extent4].[JobSeekerID] AS [JobSeekerID], [Extent3].[FirstName] AS [FirstName]
,[Extent2].[JobType] AS [JobType], [Extent2].[JobCareerLevel] AS [JobCareerLevel]
,[Extent2].[JobLocation] AS [JobLocation]
FROM [dbo].[UserInterest] AS [Extent1]
INNER JOIN [dbo].[Job] AS [Extent2] ON ([Extent1].[FunctionalId] = [Extent2].[FunctionId])
OR (([Extent1].[FunctionalId] IS NULL) AND ([Extent2].[FunctionId] IS NULL))
OR ([Extent1].[Careerlevel] = [Extent2].[CarrerLevelId])
OR (([Extent1].[Careerlevel] IS NULL) AND ([Extent2].[CarrerLevelId] IS NULL))
OR ([Extent1].[SalId] = [Extent2].[SalaryRangeId])
OR (([Extent1].[SalId] IS NULL)
AND ([Extent2].[SalaryRangeId] IS NULL))
INNER JOIN [dbo].[UserRegistration] AS [Extent3] ON [Extent2].[UserId] = [Extent3].[UserId]
INNER JOIN [dbo].[EmplrRegistration] AS [Extent4] ON [Extent2].[UserId] = [Extent4].[JobSeekerID]
WHERE (1 = [Extent1].[Status]) AND (1 = [Extent1].[UserId])
Join which contains not just AND expressions is possible via from x in entities.Where(x => ..). You have did that partially and made mistake in where condition.
Corrected query, looks the same as original SQL
var query =
from m in entities.UserInterests
from j in entities.Jobs.Where(j =>
m.FunctionalId != null && m.FunctionalId == j.FunctionId ||
m.Careerlevel != null && m.Careerlevel == j.CarrerLevelId ||
m.SalId != null && m.SalId == j.SalaryRangeId)
join ur in entities.UserRegistrations on j.UserId equals ur.UserId
join r in entities.EmplrRegistrations on j.UserId equals r.JobSeekerID
where m.Status == true && m.UserId == 1
select new { r.CompanyLogo, j.JobName, j.JobId, ur.UserId, r.JobSeekerID
, ur.FirstName, j.JobType, j.JobCareerLevel, j.JobLocation };
var list = query.Distinct().ToList();

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)

EntityFramework = LINQ

I've got some legacy code where there is a lot of raw SQL statements which I try to port to LINQ.
One of them looks like this
select s.Id, s.Name, s.Enabled, s.Tags, s.Description, s.ImageUrl, s.ImageFullUrl, sss.Id as StoneSupplierStoneId
from Stone s, StoneSupplierStone sss
where s.Id = sss.Stone_id and s.Enabled = 1
and sss.Id IN (select MAX(sss.Id)
from Stone s, StoneSupplierStone sss
where sss.StoneSupplier_id = 6142
and s.Id = sss.Stone_id and s.Enabled = 1
group by s.Name, (case when sss.CustomStoneName is null then s.Name else sss.CustomStoneName end))
order by s.Name
which I managed to port to LINQ using something like this
var sssq = from s in Stone
from sss in StoneSupplierStone
where sss.StoneSupplier_id == 6142
&& s.Id == sss.Stone_id
&& s.Enabled == true
let res = new { s.Name, sssName = sss.CustomStoneName == null ? s.Name : sss.CustomStoneName, sss.Id }
group res by new { res.Name, res.sssName } into g
select new { sssId = g.Max(_ => _.Id) };
var q = from s in Stone
from sss in StoneSupplierStone
where s.Id == sss.Stone_id
&& s.Enabled == true
&& sssq.Any(_ => _.sssId == sss.Id)
orderby s.Name
select new { s.Id, s.Name, s.Enabled, s.Tags, s.Description, s.ImageUrl, s.ImageFullUrl, StoneSupplierStoneId = sss.Id };
while I do get the same results, the underlying generated query looks pretty weird
-- Region Parameters
DECLARE #p0 Int = 1
DECLARE #p1 Int = 6142
DECLARE #p2 Int = 1
-- EndRegion
SELECT [t0].[Id], [t0].[Name], [t0].[Enabled], [t0].[Tags], [t0].[Description], [t0].[ImageUrl], [t0].[ImageFullUrl], [t1].[Id] AS [StoneSupplierStoneId]
FROM [Stone] AS [t0], [StoneSupplierStone] AS [t1]
WHERE (([t0].[Id]) = [t1].[Stone_id]) AND ([t0].[Enabled] = #p0) AND (EXISTS(
SELECT NULL AS [EMPTY]
FROM (
SELECT MAX([t4].[Id2]) AS [value]
FROM (
SELECT [t2].[Id], [t2].[Name], [t2].[Enabled], [t3].[Id] AS [Id2], [t3].[StoneSupplier_id], [t3].[Stone_id],
(CASE
WHEN [t3].[CustomStoneName] IS NULL THEN [t2].[Name]
ELSE CONVERT(NVarChar(256),[t3].[CustomStoneName])
END) AS [value]
FROM [Stone] AS [t2], [StoneSupplierStone] AS [t3]
) AS [t4]
WHERE ([t4].[StoneSupplier_id] = #p1) AND (([t4].[Id]) = [t4].[Stone_id]) AND ([t4].[Enabled] = #p2)
GROUP BY [t4].[Name], [t4].[value]
) AS [t5]
WHERE [t5].[value] = [t1].[Id]
))
ORDER BY [t0].[Name]
is there a way to rewrite my LINQ query to make it look more like the original SQL query?
P.S. I use LinqPad to test LINQ and generated query.

LINQ query with sub where clause

I have a SQL query :
SELECT [Paypoint]
,[Department]
,[EmployeeCode]
,[Gender]
,[EmployeeTitle]
,[Initials]
,[Surname]
,[ItemsIssuedDate]
,[ItemsIssuedStockNumber]
FROM [MyTable] AS a
WHERE
(
[ItemsIssuedDate] = ( SELECT max([ItemsIssuedDate])
FROM [MyTable] AS b
WHERE a.[Paypoint] = b.[Paypoint]
AND a.[Department] = b.[Department]
AND a.[EmployeeCode] = b.[EmployeeCode]
AND a.[Gender] = b.[Gender]
AND a.[Surname] = b.[Surname]
)
How would one get the comparitive LINQ query ? I cannot use the SQL query as the Data is already in a DataSet, and now needs to be modified further...
I have attempted, but this does not work :
var query = from a in excelTable
where
(
from c in excelTable
group c by new
{
c.Paypoint,
c.EmployeeCode
} into g
where string.Compare(a.Paypoint, g.Key.Paypoint) == 0 && string.Compare(a.EmployeeCode, g.Key.Paypoint) == 0
select g.Key.Paypoint
)
select a;
var query = from a in MyTable
group a by new {
a.Paypoint,
a.Department,
a.EmployeeCode,
a.Gender,
a.Surname
} into g
select g.OrderByDescending(x => x.ItemsIssuedDate)
//.Select(x => new { required properties })
.First();
You can also select anonymous object with required fields only. Up to you.
Your most direct with the SQL query will be:
var query =
from a in excelTable
let maxIssueDate =
(from b in excelTable
where a.Paypoint == b.Paypoint &&
a.Department == b.Department &&
a.EmployeeCode == b.EmployeeCode &&
a.Gender == b.Gender &&
a.Surname == b.Surname
select b.ItemsIssueDate).Max()
where a.ItemsIssueDate == maxIssueDate
select a;

Conceptualizing an advanced linq query using multifield filtering

I've been scouring the internet and every example I've found so far uses the same sort of a query to perform a search. I find this the hello world version of a search. I've found a few that use an if statement to select between a few queries, but still lack any real power.
(from c in context.table
where c.contains(searchField)).toList());
The search is so simple that I can not come up with how I would develop a search query for the below screenshot. Checkbox groups should create OR/IN clauses and pretty much everything else is an AND
for instance, the users checks Sarasota, Venice enters a yearbuilt 1990 and selects bedrooms 1+ and enters a sale date range from 1/1/2000 and leaves the to fieldblank.
in plain old SQL this would be.
where city = 'sarasota' or city = 'Venice' AND yearbuilt = 1990 AND bedrooms >= 1 AND fromSaleDate >= 1/1/2000 AND toSaleDate = 12/31/9999
if I was using old school sql strings and ASP classic I would use a combination of hardcoded clauses and few ifs and for statements to dynamically build the query string myself.
I'm envisioning a searchViewModel (yet to be written) of somekind that passes the values in somehow. So I can't include a code sample of that ViewModel. And the real kicker is the Property Features section. That will be a dynamic list of available property features, so hardcoding that as part of the query is not an option.
I think somehow this might be relevant but I'm not sure. filtering a list using LINQ
Please help me take a step in the right direction. Thanks
Update
Here is the query as executed in Profiler. I tweaked it to declare the variables so I could run it interactively, but the query itself is unaltered
declare #p__linq__0 as datetime
declare #p__linq__1 as datetime
set #p__linq__0='1989-01-01 00:00:00'
set #p__linq__1='1990-01-01 00:00:00'
SELECT TOP (10)
[Project3].[STRAP] AS [STRAP],
[Project3].[SITUS] AS [SITUS],
[Project3].[MAILING_ADDRESS] AS [MAILING_ADDRESS],
[Project3].[PROPERTY_USE] AS [PROPERTY_USE],
[Project3].[SUBDIVISION] AS [SUBDIVISION],
[Project3].[DSCR] AS [DSCR],
[Project3].[LAND_AREA] AS [LAND_AREA],
[Project3].[INCORPORATION] AS [INCORPORATION],
[Project3].[SEC_TWP_RGE] AS [SEC_TWP_RGE],
[Project3].[CENSUS] AS [CENSUS]
FROM ( SELECT [Project3].[STRAP] AS [STRAP], [Project3].[SITUS] AS [SITUS], [Project3].[MAILING_ADDRESS] AS [MAILING_ADDRESS], [Project3].[PROPERTY_USE] AS [PROPERTY_USE], [Project3].[SUBDIVISION] AS [SUBDIVISION], [Project3].[DSCR] AS [DSCR], [Project3].[LAND_AREA] AS [LAND_AREA], [Project3].[INCORPORATION] AS [INCORPORATION], [Project3].[SEC_TWP_RGE] AS [SEC_TWP_RGE], [Project3].[CENSUS] AS [CENSUS], row_number() OVER (ORDER BY [Project3].[STRAP] ASC) AS [row_number]
FROM ( SELECT
[Distinct2].[STRAP] AS [STRAP],
[Distinct2].[SITUS] AS [SITUS],
[Distinct2].[MAILING_ADDRESS] AS [MAILING_ADDRESS],
[Distinct2].[PROPERTY_USE] AS [PROPERTY_USE],
[Distinct2].[SUBDIVISION] AS [SUBDIVISION],
[Distinct2].[DSCR] AS [DSCR],
[Distinct2].[LAND_AREA] AS [LAND_AREA],
[Distinct2].[INCORPORATION] AS [INCORPORATION],
[Distinct2].[SEC_TWP_RGE] AS [SEC_TWP_RGE],
[Distinct2].[CENSUS] AS [CENSUS]
FROM ( SELECT DISTINCT
[Distinct1].[STRAP] AS [STRAP],
[Distinct1].[SITUS] AS [SITUS],
[Distinct1].[MAILING_ADDRESS] AS [MAILING_ADDRESS],
[Distinct1].[PROPERTY_USE] AS [PROPERTY_USE],
[Distinct1].[SUBDIVISION] AS [SUBDIVISION],
[Distinct1].[DSCR] AS [DSCR],
[Distinct1].[LAND_AREA] AS [LAND_AREA],
[Distinct1].[INCORPORATION] AS [INCORPORATION],
[Distinct1].[SEC_TWP_RGE] AS [SEC_TWP_RGE],
[Distinct1].[CENSUS] AS [CENSUS]
FROM (SELECT DISTINCT
[Extent1].[STRAP] AS [STRAP],
[Extent1].[SITUS] AS [SITUS],
[Extent1].[MAILING_ADDRESS] AS [MAILING_ADDRESS],
[Extent1].[PROPERTY_USE] AS [PROPERTY_USE],
[Extent1].[SUBDIVISION] AS [SUBDIVISION],
[Extent1].[DSCR] AS [DSCR],
[Extent1].[LAND_AREA] AS [LAND_AREA],
[Extent1].[INCORPORATION] AS [INCORPORATION],
[Extent1].[SEC_TWP_RGE] AS [SEC_TWP_RGE],
[Extent1].[CENSUS] AS [CENSUS]
FROM [dbo].[Properties] AS [Extent1]
INNER JOIN [dbo].[Transfers] AS [Extent2] ON [Extent1].[STRAP] = [Extent2].[STRAP]
WHERE CAST( [Extent2].[TRANS_DATE] AS datetime2) >= #p__linq__0 ) AS [Distinct1]
INNER JOIN [dbo].[Transfers] AS [Extent3] ON [Distinct1].[STRAP] = [Extent3].[STRAP]
WHERE CAST( [Extent3].[TRANS_DATE] AS datetime2) <= #p__linq__1
) AS [Distinct2]
) AS [Project3]
) AS [Project3]
WHERE [Project3].[row_number] > 0
Update
if (Model == null)
{
Model = new SearchViewModel();
}
TryUpdateModel(Model);
Model.Locations = _service.GetLocations().Select(x => new SelectListItem { Text = x.Value, Value = x.Key }).ToList();
var results = _service.GetProperties();
if (Model.SelectedLocation != null)
results = (from r in results
where r.SITUS.ToLower().Contains(Model.SelectedLocation.ToLower())
select r);
if (Model.ParcelID != null)
results = (from r in results
where r.STRAP.StartsWith(Model.ParcelID.Replace("-", "")) || r.STRAP.Equals(Model.ParcelID.Replace("-", ""))
select r);
if (Model.SqftFrom != null)
results = (from r in results
from b in r.Buildings
where b.GROSS_AREA >= Model.SqftFrom
select r).Distinct();
if (Model.SqftTo != null)
results = (from r in results
from b in r.Buildings
where b.GROSS_AREA <= Model.SqftTo
select r).Distinct();
if (Model.Bedrooms != null)
results = (from r in results
from b in r.Buildings
from s in b.StructuralElements
where s.VALUE == Model.Bedrooms && s.DSCR.ToLower() == "bedrooms"
select r).Distinct();
if (Model.Bathrooms != null)
results = (from r in results
from b in r.Buildings
from s in b.StructuralElements
where s.VALUE == Model.Bathrooms && s.CATEGORY == "BT"
select r).Distinct();
if (Model.SaleAmountFrom != null)
results = (from r in results
from t in r.Transfers
where t.AMOUNT >= Model.SaleAmountFrom
select r).Distinct();
if (Model.SaleAmountTo != null)
results = (from r in results
from t in r.Transfers
where t.AMOUNT <= Model.SaleAmountTo
select r).Distinct();
if (Model.SalesFrom != null)
results = (from r in results
from t in r.Transfers
where t.TRANS_DATE >= Model.SalesFrom
select r).Distinct();
if (Model.SalesTo != null)
results = (from r in results
from t in r.Transfers
where t.TRANS_DATE <= Model.SalesTo
select r).Distinct();
//if (Model.SalesTo != null)
// results = (from r in results
// from t in r.Transfers
// where t.TRANS_DATE <= Model.SalesTo
// select r).Distinct();
results = results.OrderBy(x => x.STRAP);
Model.SearchResults = results.ToPagedList(page ??1 , size ?? 10);
if (Model.SearchResults.Count() == 1)
{
var strap = Model.SearchResults.FirstOrDefault().STRAP;
return RedirectToRoute("Details", new { id = strap });
}
else
{
return View(Model);
}
LINQ sources (IQueryable<T>) are composable, so you can do:
IQueryable<Parcel> query = ctx.Parcels;
if(location != null)
query = query.Where(x => x.Location == location);
if(tennisCourt)
query = query.Where(x => x.HasTennisCourt);
if(minSaleDate != null)
query = query.Where(x => x.SaleDate >= minSaleDate.Value);
if(maxSaleDate != null)
query = query.Where(x => x.SaleDate <= maxSaleDate.Value);
then finally you can do:
// first 50, plus a final one to display "more..." link
var page = query.Take(51).ToList();
or:
int count = query.Count();
And the trick is: it only executes the fully composed query - i.e. anything that either enumerates the query (foreach, ToList, etc), or aggregates the query (Count, Sum, etc)

Categories

Resources