modify linq to get first 5 elements - c#

var lastArticles = from a in be.MyTable
where a.id == 1
join c in be.OtherTable on a.parent equals c.id
orderby a.timestamp descending
select new { a, cName = c.name};
I need to get the first 5 elements.
I'm doing it by
.Take(5)
but is there a way to do in in the linq statement?

No, you need to use Skip() and Take() as method calls. There is no LINQ-specific equivalent.
var lastArticles = (from a in be.MyTable
where a.id == 1
join c in be.OtherTable on a.parent equals c.id
orderby a.timestamp descending
select new { a, cName = c.name }).Take(5);

A linq Query should always be separate from the products of running that query.
.Take() produces results, and thus should be separate and distinct from the query.
//data query
var lastArticlesQuery = from a in be.MyTable
where a.id == 1
join c in be.OtherTable on a.parent equals c.id
orderby a.timestamp descending
select new { a, cName = c.name};
//results of that query at this time
var lastArticles = lastArticlesQuery.Take(5);

This code is only syntatic sugar, utlimately it will be converted to a LINQ-methods chain that will look something like:
var lastArticles = be.MyTable
.Where(a => a.id == 1)
.Join(be.OtherTable, a => a.parent, c => c.id,
(a, c) => new { a, c})
.OrderByDescending(#t => #t.a.timestamp)
.Select(#t => new { #t.a, cName = #t.c.name });
So having a keyword for Take() would only add to the sytactic sugar and it would need to be re-converted as well.
In short, no, the only way is to use the Take() method.

Related

Select multiple joined tables into multiple variables in SQL queries or LINQ

SELECT O.*, U.*, C.*, P.*, S.*
INTO OV, Usuarios, Clientes, Proposta, Status
FROM[dbo].[TB_OV] O
INNER JOIN dbo.TB_Usuarios U on U.id = O.userinsert
INNER JOIN dbo.TB_Clientes C on C.id = O.ENDFAT
INNER JOIN dbo.TB_Status S on S.id = O.status
LEFT JOIN TB_Proposta P on P.id = O.ID_PROP
WHERE O.status = 214 ORDER BY O.DTSOL, O.DtdeFaturamento
I am developing a web system in C# and one of the queries that I am trying to do is this one...
I want to know what is the correct syntax to do that or something like this.
What I need to know exactly is how to select this five tables into five different variables like an object to each one that I can cast later in C# to turn into object typed.
Otherwise, I've tried to do it with LINQ to SQL from C# and I still did not get any results from queries in LINQ to SQL to these tables.
Lambda:
var query = db.TB_OV
.Join(db.TB_Usuarios, OV => OV.USERINSERT, U => U.ID, (OV, U) => new { OV, U })
.Join(db.TB_Clientes, Z => Z.OV.ENDFAT, CL => CL.ID, (Z, CL) => new { Z, CL })
.Join(db.TB_Status, Z => Z.Z.OV.STATUS, ST => ST.ID, (Z, ST) => new { Z, ST })
.Join(db.TB_Proposta, Z => Z.Z.Z.OV.ID_PROP, P => P.ID, (Z, P) => new { Z, P })
.Where(Z => Z.Z.Z.Z.OV.STATUS == 214)
.Select(Z => new OperacoesListaSolFaturamento
{
OV = Z.Z.Z.Z.OV,
Usuarios = Z.Z.Z.Z.U,
Clientes = Z.Z.Z.CL,
Status = Z.Z.ST,
Proposta = Z.P
});
Fluent:
var query = from O in db.TB_OV
join U in db.TB_Usuarios on O.USERINSERT equals U.ID
join C in db.TB_Clientes on O.ENDFAT equals C.ID
join S in db.TB_Status on O.STATUS equals S.ID
join P in db.TB_Proposta on O.ID_PROP equals P.ID
where O.STATUS == 214
select new OperacoesListaSolFaturamento
{
OV = O,
Usuarios = U,
Clientes = C,
Status = S,
Proposta = P
};
Is there any way to do that? Either by LINQ or SQL queries.
For translating SQL to LINQ query comprehension:
Translate FROM subselects as separately declared variables.
Translate each clause in LINQ clause order, translating monadic and aggregate operators (DISTINCT, TOP, MIN, MAX etc) into functions applied to the whole LINQ query.
Use table aliases as range variables. Use column aliases as anonymous type field names.
Use anonymous types (new { ... }) for multiple columns.
LEFT JOIN is simulated by using into joinvariable and doing another from from the joinvariable followed by .DefaultIfEmpty().
Replace COALESCE with the conditional operator (?:)and a null test.
Translate IN to .Contains() and NOT IN to !...Contains().
Translate x BETWEEN low AND high to low <= x && x <= high.
SELECT * must be replaced with select range_variable or for joins, an anonymous object containing all the range variables.
SELECT fields must be replaced with select new { ... } creating an anonymous object with all the desired fields or expressions.
Proper FULL OUTER JOIN must be handled with an extension method.
So the main problem with your fluent query is you didn't translate the LEFT JOIN properly:
var query = from O in db.TB_OV
where O.STATUS == 214
join U in db.TB_Usuarios on O.USERINSERT equals U.ID
join C in db.TB_Clientes on O.ENDFAT equals C.ID
join S in db.TB_Status on O.STATUS equals S.ID
join P in db.TB_Proposta on O.ID_PROP equals P.ID into Pj
from P in Pj.DefaultIfEmpty()
orderby O.DTSOL, O.DtdeFaturamento
select new OperacoesListaSolFaturamento
{
OV = O,
Usuarios = U,
Clientes = C,
Status = S,
Proposta = P
};

Distinct record using linq in entity framework

According to this query i get all records which have same id but i want only one time that record
var query = (from c in CompObj.EmpInfoes
join d in CompObj.Leaves on c.EmpID equals d.ProjectManagerID
where c.RoleID == 4 || c.RoleID == 2
select new { c.EmpName, c.EmpID });
var query = (from c in CompObj.EmpInfoes
join d in CompObj.Leaves on c.EmpID equals d.ProjectManagerID
where c.RoleID == 4 || c.RoleID == 2
select new { c.EmpName, c.EmpID })
.Distinct();
Or was there something more you needed?
Just add .Distinct() at the end.

How can I write a linq query for this?

I need to write following query in Linq to SQL but not sure what is the best way of doing, given it has two derived tables. Any suggestions.
SELECT A.ID
FROM
(
SELECT *
FROM Orders
WHERE ProductID = 5
) A
JOIN
(
SELECT CustomerID, MAX(Price) Price
FROM Orders
WHERE ProductID = 5
GROUP BY CustomerID
) B
ON A.CustomerID = B.CustomerID and A.Price = B.Price
var b = (
from o in db.Orders
where o.ProductID == 5
group o by o.CustomerID into og
select new {
CustomerID = og.Key
Price = Max(og.Price)
}
);
var a = (
from o in db.Orders
join p in b on new {a.CustomerID, a.Price} equals
new {b.CustomerID, b.Price}
where o.ProductID == 5
select a.ID
);
var r = a.ToString();
These two links are invaluable when forming things like this:
http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
http://msdn.microsoft.com/en-us/vstudio/bb688085
Can you simplify this with LINQ, especially if you use method syntax instead of query syntax.
orders.Where(o => o.ProductID == 5)
.GroupBy(o => o.CustomerID)
.SelectMany(g => g.Where(o => o.Price == g.Max(m => m.Price)));
My advice when writing LINQ, do not simply attempt to convert a SQL statement exactly. Think about the desired result and develop a solution designed for LINQ.
Something along these lines:
var result = from a in context.Orders
join b in (context.Orders.Where(o => o.ProductID == 5).GroupBy(o => o.CustomerID).Select(g => new { CustomerID = g.Key, Price = g.Max(o => o.Price)))
on new {a.CustomerID, a.Price} equals new {b.CustomerID, b.Price}
where a.ProductID == 5
select a.ID;

Efficient way to sub Queries in Linq

here is my linq code:
BOOK entity = db.BOOKS
.Where(s => s.ID == (from p in db.LIBRARY
from b in db.BOOKS
where (p.ID == 123) && (p.idpage == b.idpage)
select b.fields));
My actual oracle code is:
SELECT DISTINCT BOOKS.ID
FROM LIBRARY,BOOKS
WHERE LIBRARY.ID = 123 AND LIBRARY.ID = BOOKS.ID
But its showing the error in s.ID that..
Delegate 'System.Func Project.Models.BOOKS,int,bool' does not take 1 arguments
Why does this happen? Are there any workarounds?
Your SQL is using a join, so you can do the same thing in LINQ. Either of these approaches will suffice:
// join
var query = (from b in db.BOOKS
join p in db.LIBRARY on b.IdPage equals p.IdPage
where p.ID == 123
select b.Id).Distinct();
// 2 from statements (SelectMany) can also be used as a join
var query = (from b in db.BOOKS
from p in db.LIBRARY
where p.ID == 123 && b.IdPage == p.IdPage
select b.Id).Distinct();
// fluent syntax
var query = db.BOOKS
.Where(b => db.LIBRARY.Any(p =>
p.ID == 123 && b.IdPage == p.IdPage))
.Select(b => b.Id)
.Distinct();
s.ID is comparing to an Enumerable, so you get the error.
At the end of the LINQ query, add a SingleOrDefault().
Your subquery returns a sequence of values, not a single values, so you can't compare it to a scalar property like ID. You should use First on the result of the subquery to get the first result (or Single if there should be only one)
BOOK entity = db.BOOKS
.Where(s => s.ID == (from p in db.LIBRARY
from b in db.BOOKS
where (p.ID == 123) && (p.idpage == b.idpage)
select b.fields).First());
You should be able to use the navigation properties on your BOOKS class to do something like this:
var bookIds = db.BOOKS.Where(b => b.LIBRARIES.Any(l => l.ID == 123))
.Select(b => b.ID)

'orderby' in linq using a string array c#

Say I have a method definition as such:
public CustomerOrderData[] GetCustomerOrderData(string[] CustomerIDs)
{
var query = (from a in db.Customer
join b in db.Order on a.CustomerID equals v.CustomerID
orderby CustomerIDs
select new CustomerOrderData()
{
//populate props here
}).ToArray();
}
My CustomerIDs in input param could be {"1","3","400","200"}
I want my return array to be ordered in the above fashion. Is there an easy way to achive this?
My solution was to put it into a Dictionary and then create a new array while looping through my CustomerIDs collection.
CustomerOrderData does have a property named CustomerID
If you materialize the query, you should be able to find the index of the id in your array and use it as the ordering parameter. Shown below using extension methods.
var ordering = CustomerIDs.ToList();
var query = db.Customer.Join( db.Order, (a,b) => a.CustomerID == b.CustomerID )
.AsEnumerable()
.OrderBy( j => ordering.IndexOf( j.Customer.CustomerID ) )
.Select( j => new CustomerOrderData {
// do selection
})
.ToArray();
I think this solves problem:
var orderedArray = YourCustomArray.OrderBy(s => s).ToArray();
if the customerIds always will be numbers then cast it and order it before using it into ur query
var orderedIds = CustomerIDs.Cast<int>().OrderBy(x => x);
You could use IndexOf:
orderby ContactIds.IndexOf(a.CustomerId)
Note that this might not be efficient for large sets.
You could create a structure to lookup the desired index using the customerid.
string[] CustomerIDs;
Dictionary<string, int> customerIDOrdering = CustomerIds
.Select((c, i) => new (id = c.CustomerID, i = i})
.ToDictionary(x => x.id, x => x.i);
var query = from c in ...
orderby customerIDOrdering[c.CustomerID]
...
The join clause preserves the order of the outer sequence:
"The Join operator preserves the order of the outer sequence elements, and for each outer element, the order of the matching inner sequence elements."
http://msdn.microsoft.com/en-us/library/bb394939.aspx
So you should not need to orderby at all:
from orderIndex in CustomerIDs
join a in db.Customer on orderIndex equals a.CustomerID
join b in db.Order on a.CustomerID equals v.CustomerID

Categories

Resources