Order by in Linq - linq

how can i show null or empty fields in last by apply Orderby:
here is my code.
Var movies = _db.Movies.Orderby(c => c.Category).ThenBy(n => n.Name)

If I understand your question correctly:
Var movies = _db.Movies
.OrderBy(c => c.Category==null?1:0)
.Thenby(c => c.Category).ThenBy(n => n.Name)

Related

Linq most efficient top results

I'm wondered I have a table with IDs and a version and a remove field. I d like to return the the top 20 records grouped by ID and for ech ID take only the highest version unless remove is set then ignore removed records.
Then return a descending record set.
There are a few ways todo it with Linq but I wonder is there a most efficient way, are there patterns to avoid?.
...
.OrderByDescending(x=>x.id)
.GroupBy(x=>x.id)
.SelectMany(y=>y.Where(x=>x.Version == y.Max(y=>y.Version)))
.Where(x=>x.Remove=false)
.Take(20)
One of then possible workarounds when using EF Core. I'm calling it workaround because with SQL and Window functions we can create more effective query.
var itemsQuery = ctx.SomeTable
.Where(x => x.Remove = false);
var query =
from d in itemsQuery.Select(d => new { d.id }).Distinct()
from x in itemsQuery.Where(x => d.Id == x.Id)
.OrderByDescending(x => x.Version)
.Take(1)
select x;
query = query.Take(20);
Similar queries when using EF Core 6:
var query = ctx.SomeTable
.Where(x => x.Remove = false)
.GroupBy(x => x.Id)
.Take(20)
.SelectMany(g => g.OrderByDescending(x => x.Version).Take(1));
var query = ctx.SomeTable
.Where(x => x.Remove = false)
.GroupBy(x => x.Id)
.Select(g => g.OrderByDescending(x => x.Version).First());
.Take(20);

Using GroupBy and show different Sums based on conditions - LINQ Lambda Expressions

I have a table with 3 columns.
And I would like to present a table with this structure:
Can someone show me how to do this with Lambda expressions?
So far I've only gotten the result if I only wanted to show one column:
var sum_data = _context.HechosFinanza
.Where(x => x.Product.Sale_Type == "Cash Sale")
.GroupBy(x => x.Product.Product_Name)
.Select(x => Product { Tienda = x.Key, Total = x.Sum(s =>
s.sales_amount) });
I don't know if something like this may be possible (no idea really, just trying to figure it out):
var sum_data = _context.HechosFinanza
// I remove there where condition from here
.GroupBy(x => x.Product.Product_Name)
// And I add the where condition in each sum
.Select(x => Product { Tienda = x.Key,
TotalCash = x.Sum(s => s.sales_amount).Where(s => s.Product.Sale_Type == "Cash Sale"),
TotalCredit = x.Sum(s => s.sales_amount).Where(s.Product.Sale_Type == "Credit Sale")
});
Uhm, well. It turns out I was really close.
Just had to put the 'Where' statement before.
Answer:
var sum_data = _context.HechosFinanza
// I remove there where condition from here
.GroupBy(x => x.Product.Product_Name)
// And I add the where condition in each sum
.Select(x => Product { Tienda = x.Key,
TotalCash = x.Where(s => s.Product.Sale_Type == "Cash Sale").Sum(s => s.sales_amount),
TotalCredit = x.Where(s.Product.Sale_Type == "Credit Sale") .Sum(s => s.sales_amount)
});
And done.

Nhibernate query for Any condition

I have table structure like
Product {List<Cost> Costs}
Cost{List<Invoice> Invoices, Product product}
Invoice{bool isIncluded}
Need a query to get all Products which has any Cost for which none of invoice is included (isIncluded=false for all)
I tried something like:
Product pro= null;
Product p = null;
var costQuery = QueryOver.Of<Cost>()
.JoinAlias(c => c.Product, () => p)
.Where(() => p.Id == pro.Id)
.WhereNot(c=>c.Invoices.Any(i=>i.IsIncluded))
.Select(c => c.Id);
var query = CurrentSession.QueryOver<Product>(() => pro)
.WithSubquery.WhereExists(costQuery);
Use of 'Any' in query errors out:
Unrecognised method call: System.Linq.Enumerable:Boolean
Any[Invoice](System.Collections.Generic.IEnumerable1[Trigger.StageGate.Services‌​.BusinessEntities.Invoice],
System.Func2[Trigger.StageGate.Services.BusinessEntities.Invoice,System.Boolean‌​])
try:
var costQuery = QueryOver.Of<Cost>()
.JoinAlias(c => c.Product, () => p)
.Where(() => p.Id == pro.Id)
.JoinQueryOver<Invoice>(c => c.Invoices)
.WhereNot(i => i.IsIncluded)
.Select(c => c.Id);

Show date format only and keep sorting AZ in MVCContrib Grid

I use the following LINQ to create grid model:
...
var query = from a in GetUser()
select new UserModel
{
ID = a.ID,
StartDate = a.StartDate,
EndDate = a.EndDate,
StateName = a.State.StateName,
StateID = a.StateID,
City = a.City,
};
return query;
....
and the HTML is
#Html.Grid(Model.PagedList).Columns(
col =>
{
col.For(c => c.StateName).Named("State").Attributes(#class => "row").HeaderAttributes(#class => "head");
col.For(c => c.City).Named("City").Attributes(#class => "row").HeaderAttributes(#class => "head");
col.For(c => c.StartDate).Named("Start Date").Attributes(#class => "row").HeaderAttributes(#class => "head");
col.For(c => c.EndDate).Named("End Date").Attributes(#class => "row").HeaderAttributes(#class => "head");
col.For(c => Html.ActionLink("Details", "Details", new { id = c.ID })).Named("View Details").HeaderAttributes(#class => "head").DoNotEncode();
}).Sort(Model.GridSortOptions).Attributes(#class => "grid")
The main problem is how to show only DATE without TIME part?
I tried some options but in some cases I got the errors and in other cases sorting AZ doesn't work at all.
Any clue?
Thank you!!!
Try using
col
.For(c => c.EndDate.ToLongDateString())
.Named("End Date")
.Attributes(#class => "row")
.HeaderAttributes(#class => "head");
Something a little easier I find is the Format method on the column. see docs here
So your code looks something like this:
col.For(c => c.EndDate).Format("{0:d"})
//use .Format("{0:yyyy-MM-dd}") to get 2014-10-21
If you want to use ToShortDateString then you will need to define the column name as well as the sort column name, for example:
col.For(c => c.EndDate.ToShortDateString())
.Named("End Date")
.SortColumnName("EndDate");

LINQ: How to Sum over Grouping using method style linq?

In the code below I'd like to do a sum for OBFY and CFY separately within each grouping in deptGroup. Anyone have any ideas, I've tried a coupla things but can't get it. Thanks!!
var deptGroup = prodCostsTotals.AsQueryable()
.Select(r => dt.Rows.Add(new object[]
{
Convert.ToInt32(r.Field<string>("Proc")),
r.Field<string>("UnitL"),
r.Field<Decimal?>("OBFY"),
r.Field<Decimal?>("CFY")
})).GroupBy(g => g.Field<string>("Proc"));
It seems to me you are overusing DataRows. If you had your data in a nice class, you could write it like this:
data.GroupBy(x => x.Proc)
.Select(g => new
{
Proc = g.Key,
OBFYSum = g.Sum(x => x.OBFY),
CFYSum = g.Sum(x => x.CFY)
})
But if you really want to start with a DataTable and add the intermediate result to another DataTable, you could do it like this:
prodCostsTotals.AsQueryable()
.Select(r => dt.Rows.Add(new object[]
{
Convert.ToInt32(r.Field<string>("Proc")),
r.Field<string>("UnitL"),
r.Field<Decimal?>("OBFY"),
r.Field<Decimal?>("CFY")
}))
.GroupBy(g => g.Field<string>("Proc"))
.Select(g => new
{
Proc = g.Key,
OBFYSum = g.Sum(x => x.Field<Decimal?>("OBFY")),
CFYSum = g.Sum(x => x.Field<Decimal?>("CFY"))
})
Note that I have no idea whether your use of AsQueryable() will have any effect on the first part of this query, but it certainly won't have any effect on the grouping.

Resources