Convert Sql to linq with groupby - c#

I have view on which I use this request
Select Spendband, SUM(SpendCurrencyJob), SUM(SpendDocumentCount)
From analysis.vwJobSupplierMetrics
Where JobId = '500E0DD1-E3D3-4887-95EF-01D3C9EA8FD0'
Group by SpendBand
And it's running sucessfully
and get me this data
How I need to write it using linq to get same data?
I tried like this
var data = await _dbContext.VwJobSupplierMetrics.Where(x => x.JobId == jobId)
.GroupBy(x => x.SpendBand)
.Select(x => new HumpChartDto() {SpendBand = x.SpendBand}).ToListAsync();
But on new HumpChartDto() {SpendBand = x.SpendBand} I got Cannot resolve symbol 'SpendBand
How I can solve this?

First, after grouping on SpendBand, you need to access it via Key property. Second, to compute Sum, you can use Sum method.
var data = await _dbContext.VwJobSupplierMetrics.Where(x => x.JobId == jobId)
.GroupBy(x => x.SpendBand)
.Select(x => new HumpChartDto()
{
SpendBand = x.Key,
SumOfSpendCurrencyJob = x.Sum(s => s.SpendCurrencyJob),
SumOfSpendDocumentCount= x.Sum(s => s.SpendDocumentCount),
})
.ToListAsync();
Note - change the property name accordingly for name I've used for SumOfSpendCurrencyJob and SumOfSpendDocumentCount as don't know the definition of HumpChartDto class.

Related

convert dictionary to list model

var entity = await _abcRepository.get(Id);
var X = entity.GroupBy(c => c.number).Where(grp => grp.Count() == 1).Take(10).ToList();
in images you see [0] and inside of it one more [0].
How can I get that model value.
X[0][0] is not working.
X.Value is not working.
I need to convert that dictionary to model.
Use .Select to normalize aggregation as per your wish.
var X = entity.GroupBy(c => c.number).Where(grp => grp.Count() == 1)
.Select(group => new { GroupKey = group.Key, Items = group.ToList() })
.Take(10).ToList();
You could try something like this:
var entity = await _abcRepository.get(Id);
var results = entity.GroupBy(c => c.number)
.Where(grp => grp.Count() == 1)
.Take(10)
.ToDictionary(grp => grp.Key, grp => grp.First());
Essentially, the lambda you pass in Where method certifies that the groups are created contains only one item. That being said, you can use the First on each group to fetch that one element.

Distinct in LINQ and change result type

I am trying to get a list of distinct items from a database.
I want the result to be in a list of CarMakes, which has only one property called Make.
I can get the following items to work in LINQPad, but when I try to get it working in C#. I get the following error
" .First()' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(),"
var result = await _context.Cars
.GroupBy(x => x.Make)
.Select(x => x.First().Make )
.ToListAsync();
I have tried the following, which can all the makes, but its not distinct.
var result = await _context.Cars
.Select(x => new CarMakes() { Assembly = x.Assembly })
.ToListAsync();
The Car table has the following columns, Id, Colour, Make, Model, Registration
I tried using MORELinq but couldnt get that working to
Try this:
var result = await _context.Cars.Select(c => c.Make).Distinct()
.Select(m => new CarMakes { Assembly = m })
.ToListAsync();
Could you try running the code below:
var result = await _context.Cars
.GroupBy(x => x.Make)
.Select(x => x.Key )
.ToListAsync();
Hope it helps! :)

EF Dynamic Field Select using LINQ

I have the following select:
var sortedCodes = Codes
.Where(c => c.Active)
.OrderByDescending(x => x.SortOrder)
.Select(b => new { b.Display, b.NumericCode, b.SortOrder })
.Distinct()
.ToList();
The table Code has many columns such as NumericCode, TextCode, AlphaCode, ThreeCode, FourCode, FiveCode. I am using this table to build selects in my UI. Is there a way I can create some dynamic code so I can pass in the column name to use for the value?
The above select would look like this:
.Select(b => new { b.Display, "TextCode", b.SortOrder })
I was thinking I could use an Expression, but I do not think this is exactly what I need as it is actually printing the lambda as the value.
var arg = Expression.Parameter(typeof(Code), "b");
var body = Expression.Property(arg, valueColumn);
var lambda = Expression.Lambda<Func<Code, string>>(body, arg);
var sortedCodes = Codes
.Where(c => c.Active)
.OrderByDescending(x => x.SortOrder)
.Select(b => new { b.Display, Value=lambda, b.SortOrder })
.Distinct()
.ToList();

LINQ - How to get subset of columns after GroupBy

This LINQ-to-SQL query works (testing in LINQpad):
var q5 = LOGs.Where(r => r.APP_NAME == "Toaster")
.GroupBy(pol => pol.CASE_NO)
.Select(grp => grp.First())
.OrderByDescending(l => l.WHEN);
q5.Dump();
However, that returns all columns for each row.
How can I refine the Select() part to specify certain columns?
I can do it in two steps by adding .ToList() to the query, then querying q5:
var q5a = q5.Select(r => new {CASE=r.CASE_NO, WHEN = r.WHEN});
q5a.Dump();
Can I accomplish that in one statement instead of two?
Thanks --
why don't you filter after where?
var q5 = LOGs.Where(r => r.APP_NAME == "Toaster")
.Select(r=> new{r.CASE_NO, r.WHEN})
.GroupBy(pol => pol.CASE_NO)
.Select(grp => grp.First())
.OrderByDescending(l => l.WHEN);
remembar that new {CASE=r.CASE_NO, WHEN = r.WHEN} creates a new anonymous type because of differents property names, new {r.CASE_NO, r.WHEN} doesn't !

Difficulty with LINQ Query writing custom sort logic

I have files like Avinash_Create.sql, Avinash_Insert.sql, Avinash_Update.sql , Avinash_Delete.sql.
I need to iterate over the files list and group them based on the name and order by create, insert, update, and delete files.
I am finding it difficult difficult to accomplish. This is what I have so far:
var userGroups = shortfilenames.GroupBy(s => s.Substring(0, s.IndexOf('_')))
.Select(g => g.OrderBy(x => x.Substring(x.IndexOf('_')).Contains("CREATE"))
.ThenBy(x => x.Substring(x.IndexOf('_')).Contains("INSERT"))
.ThenBy(x => x.Substring(x.IndexOf('_')).Contains("UPDATE"))
.ThenBy(x => x.Substring(x.IndexOf('_')).Contains("DELETE")));
The above query is grouping by name 'Avinash' but not working for custom ordering. Please help.
Update:
Please see updated query , still it is not sorting properly
Uses Split to extract the relevant sections of the string. Converts the result to upper case, which seems to be missing from your attempt. Additionally makes it a bit shorter by using an array to hold your custom sort order and then Array.IndexOf to get a sort order from it, rather than multiple OrderBy/ThenBy.
var ordering = new [] {"CREATE", "INSERT", "UPDATE", "DELETE"};
var results = shortfilenames.GroupBy(s => s.Split('_')[0])
.Select(g => g.OrderBy(x => Array.IndexOf(ordering, x.Split('_')[1].Split('.')[0].ToUpper())));
This seems to be what what you want:
var shortfilenames = new List<string>(){"Avinash_Create.sql" , "Avinash_Insert.sql" , "Avinash_Update.sql" , "Avinash_Delete.sql"};
var userGroups = shortfilenames
.Select(fn =>
{
string fileName = Path.GetFileNameWithoutExtension(fn);
string[] nameAndAction = fileName.Split('_');
return new
{
extension = Path.GetExtension(fn),
fileName,
name = nameAndAction[0],
action = nameAndAction[1]
};
})
.GroupBy(x => x.name)
.Select(g => g.OrderByDescending(x => x.action.Equals("CREATE", StringComparison.InvariantCultureIgnoreCase))
.ThenByDescending(x => x.action.Equals("INSERT", StringComparison.InvariantCultureIgnoreCase))
.ThenByDescending(x => x.action.Equals("UPDATE", StringComparison.InvariantCultureIgnoreCase))
.ThenByDescending(x => x.action.Equals("DELETE", StringComparison.InvariantCultureIgnoreCase))
.ToList());
foreach (var ug in userGroups)
foreach (var x in ug)
Console.WriteLine("{0} {1}", x.name, x.action);
prints out:
Avinash Create
Avinash Insert
Avinash Update
Avinash Delete
Presumes that the file-names always contain the underscore.

Categories