Convert SQL(Row_Number) Query into Linq in MVC? - c#

How to convert below SQL Query to Linq expression in C#(MVC)?
with cte
as
(
select *,rank() over(partition by LineClass order by LineClassId) as rownum
from MT_LineClass where ProjectId =1
)
select * from cte where rownum=1

var res = from tbl in MT_LineClass
group tbl.lineclassid by tbl.lineclass into g
select new { LineClass = g.Key, LineClassIds = g.ToList() };
You can use other than ToList operations to get the id (eq First, Max etc)

var lst = (from t in context.MT_LineClass
where t.ProjectId == projId
group t by t.LineClass into g
select new Mt_Lineclass
{
lineId = g.Select(t => t.LineClassId).FirstOrDefault(),
Lineclass = g.Select(t => t.LineClass).FirstOrDefault()
}).ToList();

Related

Perform SELECT statement on another SELECT using LINQ

In my .NET Core app, I have the following in LINQ:
return await db.ApplicationUsers.Where(u=>u.Name.Contains(name) && !u.Deleted && u.AppearInSearch)
.OrderByDescending(u => u.Verified)
.Skip(page * recordsInPage)
.Take(recordsInPage)
.Select(u => new UserSearchResult()
{
Name = u.Name,
Verified = u.Verified,
PhotoURL = u.PhotoURL,
UserID = u.Id,
Subdomain = u.Subdomain
}).ToListAsync();
which translates to the following SQL:
SELECT [t].[Name], [t].[Verified],
[t].[PhotoURL], [t].[Id],
[t].[Subdomain]
FROM
(SELECT [u0].*
FROM [AspNetUsers] AS [u0]
WHERE (((CHARINDEX('khaled', [u0].[Name]) > 0) OR ('khaled' = N''))
AND ([u0].[Deleted] = 0))
AND ([u0].[AppearInSearch] = 1)
ORDER BY [u0].[Verified] DESC
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY ) AS [t]
But due to performance issues, Microsoft support suggested that I only query columns of fixed length (not varchar(max)). I was asked to change the SQL query to:
SELECT [t].[Name], [t].[Verified],
[t].[PhotoURL] , [t].[Id], [t].[Subdomain]
FROM
(Select u0.Name, u0.Verified, u0.PhotoURL, u0.id, u0.Subdomain,
u0.Deleted, u0.AppearInSearch FROM [AspNetUsers] ) As [u0]
WHERE (((CHARINDEX('khaled', [u0].[Name]) > 0) OR ('khaled' = N''))
AND ([u0].[Deleted] = 0))
AND ([u0].[AppearInSearch] = 1)
ORDER BY [u0].[Verified] DESC
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY ) AS [t]
Which is a SELECT on another SELECT. Unfortunately I don't know how to do it in LINQ. Can someone please guide me how to make the second SQL query in LINQ?
Thank you
First build the inner select:
var s1 = from u in db.AspNetUsers
select new UserSearchResult
{
Name = u.Name,
Verified = u.Verified,
PhotoURL = u.PhotoURL,
UserID = u.Id,
Subdomain = u.Subdomain
};
then use it in the outer select:
return await (from u1 in s1
where u.Name.Contains(name) && !u.Deleted && u.AppearInSearch
orderby u.Verified
select u1)
.Skip(page * recordsInPage)
.Take(recordsInPage);
When you make the output of select query .ToList(), the output is a list again. Over this list you can apply another .Select(). So, as in your previous query, you can do it as:
return await db.ApplicationUsers.Where(u=>u.Name.Contains(name) && !u.Deleted && u.AppearInSearch)
.OrderByDescending(u => u.Verified)
.Skip(page * recordsInPage)
.Take(recordsInPage)
.Select(u => new UserSearchResult()
{
Name = u.Name,
Verified = u.Verified,
PhotoURL = u.PhotoURL,
UserID = u.Id,
Subdomain = u.Subdomain
})
.ToList()
.Select(<your new query>)
.ToListAsync();

SQL ROW_NUMBER() in LINQ Query Syntax

I have this query which I wish to replace with Linq as query syntax:
select
ii.Id, ii.Name as Supplier,
qi.Price1, qi.Price2, qi.Price3,
case when qi.price1 is null then NULL else ROW_NUMBER() OVER(ORDER BY isNull(qi.price1,1000000) ASC) end AS Price1Order,
case when qi.price2 is null then NULL else ROW_NUMBER() OVER(ORDER BY isNull(qi.price2,1000000) ASC) end AS Price2Order,
case when qi.price3 is null then NULL else ROW_NUMBER() OVER(ORDER BY isNull(qi.price3,1000000) ASC) end AS Price3Order
From dbo.InquiryItems ii
left join dbo.quoteItems qi on ii.Id = qi.QuoteItem_InquiryItem
SQL-Query Result:
Id Supplier Price1 Price2 Price3 Price1Order Price2Order Price3Order
1655 Supplier 2 80.00 NULL 40.00 3 NULL 1
1656 Supplier 4 65.00 30.00 42.00 2 1 2
1662 Supplier 1 15.00 35.00 43.00 1 2 3
1670 Supplier 3 250.00 NULL NULL 4 NULL NULL
In C# I need this query as a IQueryable Object. I must filter the query for different parts (one or more) and then group it by Supplier (IdAccount) and SUM the prices. This prices I must rank.
return colQuoteItem = from vQuote in this.vQuoteItemOverviews
where vQuote.IdConstructionStageId == ConstructionStageId
group vQuote by new
{
vQuote.IdAccount
} into g
select new vQuoteItemOverviewSum
{
Id = g.Max(x => x.Id),
Price1Order = null, //Here I need the ROW_NUMBER like in the SQL-Syntax
Price2Order = null, //Here I need the ROW_NUMBER like in the SQL-Syntax
Price3Order = null, //Here I need the ROW_NUMBER like in the SQL-Syntax
price1 = g.Sum(x => x.price1),
price2 = g.Sum(x => x.price2),
price3 = g.Sum(x => x.price3),
}
;
Would this work?
var qi1 = (from qi in quoteItems orderby qi.price1 select new {qi.QuoteItem_InquiryItem}).AsEnumerable().Select((i, index) => new {i.QuoteItem_InquiryItem, Rank = index + 1});
var qi2 = (from qi in quoteItems orderby qi.price2 select new {qi.QuoteItem_InquiryItem}).AsEnumerable().Select((i, index) => new {i.QuoteItem_InquiryItem, Rank = index + 1});
var qi3 = (from qi in quoteItems orderby qi.price3 select new {qi.QuoteItem_InquiryItem}).AsEnumerable().Select((i, index) => new {i.QuoteItem_InquiryItem, Rank = index + 1});
return colQuoteItem = from vQuote in this.vQuoteItemOverviews.AsEnumerable()
where vQuote.IdConstructionStageId == ConstructionStageId
group vQuote by new
{
vQuote.IdAccount
} into g
select new vQuoteItemOverviewSum
{
Id = g.Max(x => x.Id),
Price1Order = qi1.FirstOrDefault(_ => _.IdConstructionStageId == x.Id)?.Rank, //Here i need the ROW_NUMBER like in the SQL-Syntax
Price2Order = qi2.FirstOrDefault(_ => _.IdConstructionStageId == x.Id)?.Rank, //Here i need the ROW_NUMBER like in the SQL-Syntax
Price3Order = qi3.FirstOrDefault(_ => _.IdConstructionStageId == x.Id)?.Rank, //Here i need the ROW_NUMBER like in the SQL-Syntax
price1 = g.Sum(x => x.price1),
price2 = g.Sum(x => x.price2),
price3 = g.Sum(x => x.price3),
}
;

Get additional attributes from group key

I have another problem with LINQ, So what I'm trying to do is create a list of best salesman. My table of sold_items, looks like this
[ID]
[Name]
[Price]
[Sold_date]
[Salesman_ID]
and the table of Salesmans
[ID]
[Login]
[First_name]
[Surname]
I want to sum all the prices, that each individual salesman sold and also have an option to group it by date for example, the best of this month, or this week
var query1 = from s in context.Archive
//join us in context.Users
//on s.Salesman.ID equals us.ID
group s by s.Salesman.ID
into g
orderby g.Sum(o => o.Price) descending
select new
{
Salesman_ID = g.Key,
Sale = g.Sum(o => o.Price),
};
that works fine, but I only get salesman_ID, how to add User First_name and Surname from Salesmans table?
You could do something like this:
var query1 =
from s in context.Archive
group s by s.Salesman into g
orderby g.Sum(o => o.Price) descending
select new
{
Salesman_ID = g.Key.ID,
Salesman_First_name = g.Key.First_name,
Salesman_Surname = g.Key.Surname,
Sale = g.Sum(o => o.Price),
};
And to limit it my a specific date, use something like this:
var query1 =
from s in context.Archive
where s.Sold_date >= minDate && s.Sold_date <= maxDate
group s by s.Salesman into g
orderby g.Sum(o => o.Price) descending
select new
{
Salesman_ID = g.Key.ID,
Salesman_First_name = g.Key.First_name,
Salesman_Surname = g.Key.Surname,
Sale = g.Sum(o => o.Price),
};
You can group by multiple columns (all the columns you want to retrieve)
var query1 = from s in context.Archive
//join us in context.Users
//on s.Salesman.ID equals us.ID
group s by new // group by multiple columns
{
s.Salesman.Id,
s.first_name,
s.surname,
} into g
orderby g.Sum(o => o.Price) descending
select new
{
Salesman_ID = g.Key,
FirstName = g.first_name,
Surname = g.surname,
Sale = g.Sum(o => o.Price),
};
Change the current Line to this.
select new { Salesman_ID = g.Key, Salesman_First_Name = g.Key.First_name };

How can I filter results of one LINQ query based on another?

Given the following:
DP_DatabaseTableAdapters.EmployeeTableAdapter employeetableAdapter = new DP_DatabaseTableAdapters.EmployeeTableAdapter();
DP_Database.EmployeeDataTable employeeTable = employeetableAdapter.GetData();
var leadEmployees = from e in employeeTable
where e.IsLead == true
select e;
DP_DatabaseTableAdapters.LaborTicketTableAdapter tableAdapter = new DP_DatabaseTableAdapters.LaborTicketTableAdapter();
DP_Database.LaborTicketDataTable table = tableAdapter.GetDataByDate(date.ToString("MM/dd/yyyy"));
var totHours = from l in table
join e in leadEmployees on l.EmployeeID equals e.EmployeeID
group l by l.EmployeeID into g
orderby g.Key
select new
{
EmployeeID = g.Key,
HoursWorked = g.Sum(s => s.HoursWorked)
};
Total hours correctly filters the results based on the leadEmployee's list of people who have the IsLead bit set to true.
I would like to know how to do this with a where clause, I have attempd to use leadEmployees.Contanis but it wants a whole EmployeeRow...
How can I add what looks to be part of an IN clause to a where filter to replace the join?
var totHours = from l in table
where ??????
group l by l.EmployeeID into g
orderby g.Key
select new
{
EmployeeID = g.Key,
HoursWorked = g.Sum(s => s.HoursWorked)
};
The contains will only want a whole EmployeeRow if you are selecting whole employee roles. You can either:
leadEmployees.Select(e => e.id).contains
OR
leadEmployees.Count(e => e.id == l.id) > 0
Both will work. (Excuse slightly rushed lack of consideration for syntax accuracies).
This should work:
var leadEmployees = from e in employeeTable
where e.IsLead == true
select e.EmployeeID;
var totHours = from l in table
where leadEmployees.Contains(l.EmployeeID)
group l by l.EmployeeID into g
orderby g.Key
select new
{
EmployeeID = g.Key,
HoursWorked = g.Sum(s => s.HoursWorked)
};

LINQ to SQL in and not in

What is in and not in equals in LINQ to SQL?
For example
select * from table in ( ...)
and
select * from table not in (..)
What is equal to the above statement in LINQ to SQL?
You use, where <list>.Contains( <item> )
var myProducts = from p in db.Products
where productList.Contains(p.ProductID)
select p;
Or you can have a list predefined as such:
int[] ids = {1, 2, 3};
var query = from item in context.items
where ids.Contains( item.id )
select item;
For the 'NOT' case, just add the '!' operator before the 'Contains' statement.
I'm confused by your question. in and not in operate on fields in the query, yet you're not specifying a field in your example query. So it should be something like:
select * from table where fieldname in ('val1', 'val2')
or
select * from table where fieldname not in (1, 2)
The equivalent of those queries in LINQ to SQL would be something like this:
List<string> validValues = new List<string>() { "val1", "val2"};
var qry = from item in dataContext.TableName
where validValues.Contains(item.FieldName)
select item;
and this:
List<int> validValues = new List<int>() { 1, 2};
var qry = from item in dataContext.TableName
where !validValues.Contains(item.FieldName)
select item;
Please Try This For SQL Not IN
var v = from cs in context.Sal_Customer
join sag in context.Sal_SalesAgreement
on cs.CustomerCode equals sag.CustomerCode
where
!(
from cus in context.Sal_Customer
join
cfc in context.Sal_CollectionFromCustomers
on cus.CustomerCode equals cfc.CustomerCode
where cus.UnitCode == locationCode &&
cus.Status == Helper.Active &&
cfc.CollectionType == Helper.CollectionTypeDRF
select cus.CustomerCode
).Contains(cs.CustomerCode) &&
cs.UnitCode == locationCode &&
cs.Status == customerStatus &&
SqlFunctions.DateDiff("Month", sag.AgreementDate, drfaDate) < 36
select new CustomerDisasterRecoveryDetails
{
CustomerCode = cs.CustomerCode,
CustomerName = cs.CustomerName,
AgreementDate = sag.AgreementDate,
AgreementDuration = SqlFunctions.DateDiff("Month", sag.AgreementDate, drfaDate)
};
Please Try This For SQL IN
context.Sal_PackageOrItemCapacity.Where(c => c.ProjectCode == projectCode && c.Status == Helper.Active && c.CapacityFor.Contains(isForItemOrPackage)).ToList();

Categories

Resources