I am trying to perform Join, GroupBy two columns and select to a new list as
var v = master.Join(
detail,
o => o.Id,
d => d.OrderId,
(o, d) => new
{
DateAdded = o.DateAdded,
VatRate = d.VatRatePercentage,
InvoiceDescription = o.InvoiceDescription
}).GroupBy(c => new
{
c.DateAdded,
c.VatRate
})
.Select(gcs => new
{
DateAdded = gcs.Key.DateAdded.Date,
VatRate = gcs.Key.VatRate,
InvoiceTypeDescription = gcs.Key.InvoiceDescription,
}
).ToList();
but i get the error
'<anonymous type: DateTime DateAdded, decimal VatRate>' does not contain a definition for 'InvoiceTypeDescription' and no accessible extension method 'InvoiceTypeDescription' accepting a first argument of type '<anonymous type: DateTime DateAdded, decimal VatRate>' could be found
I would like to group by two columns (DateAdded, VatRate) but get the InvoiceDescription column also in the results. How can i fix that?
This is a sample:
var resultmutiplekeylambaorderbyelement = studentlist
.GroupBy(stu => new{stu.standard, stu.age})
.OrderBy(g => g.Key.standard).ThenBy(y=> y.Key.age)
.Select(g => new { standardkey = g.Key.standard, agekey = g.Key.age, studentobj = g.OrderBy(y => y.name) });
Related
I have below list of items:
ID Date
01200 11/11/2020
01200 11/11/2021
02100 01/01/2019
02100 01/01/2029
I am trying to group items by ID, then for each group select the item which has the Max date, and finally select the item which has the Min date. Taken into account above set of items, the final result would be 11/11/2021.
So I have implemented two ways here to do the same thing. Option 1 is working but option 2 isn't.
step-by-step:
// first get the groups:
var groups = items.GroupBy(i => i.ID);
// find the max date in each group
var maxDates = groups.Select(g => g.OrderByDescending(i => i.Date).First());
// now find the earliest max date
var minDate = maxDates.OrderBy(i => i.Date).First();
combined into one line:
var minDate = items.GroupBy(i => i.ID)
.Select(g => g.OrderByDescending(i => i.Date).First())
.OrderBy(i => i.Date).First();
...
GroupBy(p => p.id,
p => p.date,
(key, g) => new { id = key, date = g.Max() })
returns an IEnumerable of an anonymous type. You cannot convert anonymous type to type Foo via .ToList<Foo>.
You should rewrite you code to resolve compilation error as
var res2 = cv.GroupBy(
p => p.id,
p => p.date,
(key, g) => new Foo{ id = key, date = g.Max() //add here class name Foo
}).Aggregate((u,v) => u.date < v.date ? u: v);
EDIT: or if you not use Dump() to show result then you may use anonymous type in GroupBy() like:
var res2 = cv.GroupBy(
p => p.id,
p => p.date,
(key, g) => new { id = key, date = g.Max() }).Aggregate((u,v) => u.date < v.date ? u: v);
Also you may use #D Stanley idea to find Foo object like:
var minDate = cv.GroupBy(i => i.id,
p => p.date,
(key, g) => new Foo() { id = key, date = g.Max() }).OrderBy(e=>e.date).First();
I have a question regarding LINQ queries using lambda expressions. I have a fairly simple SQL query which takes the average of the rating in table CustomerFeedback, and joins the Movie table on the key movie_id.
I have written the query in SQL and LINQ sql syntax, but writing it in lambda syntax (method syntax) has been a struggle for me.
This is a primitive version of the database scheme:
TABLE Movie (
movie_id INT NOT NULL PRIMARY KEY,
title varchar(255) NOT NULL
)
TABLE CustomerFeedback (
movie_id int,
rating int
CONSTRAINT fk_CustomerFeedbackMovie FOREIGN KEY (movie_id) REFERENCES Movie (movie_id) ON UPDATE CASCADE
)
The query in SQL:
SELECT avg(rating) as AvgRating , m.movie_id as MovieID
FROM CustomerFeedback cf
INNER JOIN Movie m ON m.movie_id = cf.movie_id
GROUP BY m.movie_id
The query in LINQ without LAMBDA syntax which works:
var averages =(from movie in _context.Movie
join feedback in _context.CustomerFeedback on movie.movie_id equals feedback.movie_id
group new {movie, feedback } by new
{
movie.movie_id
}
into grouping
orderby
(double?)grouping.Average(p => p.feedback.rating) ascending
select new
{
grouping.Key.movie_id,
rating_average = (double?)grouping.Average(p => p.feedback.rating)
}).Take(10);
If anyone could give me a few pointers or a solution it would be greatly appreciated!
EDIT: The navigation properties as requested by user YacoubMassad
modelBuilder.Entity<CustomerFeedback>(entity =>
{
entity.HasKey(e => e.movie_id);
entity.Property(e => e.movie_id).ValueGeneratedNever();
entity.Property(e => e.comments)
.IsRequired()
.HasMaxLength(255)
.HasColumnType("varchar");
entity.Property(e => e.customer_mail_address)
.IsRequired()
.HasMaxLength(255)
.HasColumnType("varchar");
entity.Property(e => e.feedback_date).HasColumnType("date");
entity.HasOne(d => d.customer_mail_addressNavigation).WithMany(p => p.CustomerFeedback).HasForeignKey(d => d.customer_mail_address).OnDelete(DeleteBehavior.Restrict);
entity.HasOne(d => d.movie).WithOne(p => p.CustomerFeedback).HasForeignKey<CustomerFeedback>(d => d.movie_id).OnDelete(DeleteBehavior.Restrict);
});
List<Movie> movies = new List<Movie>() {
new Movie(){Id = 1, Name = "The Matrix"},
new Movie(){Id = 2, Name = "Captain America"}
};
List<MovieReview> reviews = new List<MovieReview>()
{
new MovieReview(){MovieId = 1, Review = 8},
new MovieReview(){MovieId = 1, Review = 7},
new MovieReview(){MovieId = 2, Review = 5}
};
//var movieReviews = reviews.GroupBy(r => r.MovieId).Select(g => new { MovieId = g.Key, AvgReview = g.Average( r => r.Review) });
var finalReviews = movies.Join(
reviews.GroupBy(r => r.MovieId).Select(g => new { MovieId = g.Key, AvgReview = g.Average(r => r.Review) }),
m => m.Id,
r => r.MovieId,
(m, r) => new { Name = m.Name, AvgReview = r.AvgReview }).ToList();
foreach (var f in finalReviews)
{
Console.WriteLine(f.Name + " " + f.AvgReview);
}
Console.ReadKey();
The entity classes
class Movie
{
public int Id = 0;
public string Name = "";
}
class MovieReview
{
public int MovieId = 0;
public int Review = 0;
}
I have a function that looks like this:
public void GetAvailableResourcesByLocationChart(List<DateTime> dates, List<ChartResourceModel> data)
{
var totals = (from r in data
group new { Dates = r.Dates } by r.Location into g
select new
{
Location = g.Key,
Dates = dates.Select(d => new
{
Date = d,
Available = g.SelectMany(x => x.Dates.Where(y => y.Date == d)).Count(x => x.Available)
})
.OrderBy(x => x.Date)
.ToList()
})
.OrderBy(x => x.Location)
.ToList();
}
This example groups the data based on Location. But I want to be able to pass in a string that specifies what it should group on. I was thinking DynamicLinq would be the right way to go about this but I'm having trouble reproducing it.
I started off doing this, but am getting stuck reproducing the SelectMany inside the select:
public void GetAvailableResourcesByLocationChart(List<DateTime> dates, List<ChartResourceModel> data, string grouping)
{
var totals = data.GroupBy(grouping, "it").Select("new (it.Key as Group, it as Dates)").Cast<dynamic>();
}
Any ideas on what I need to do next?
this
from r in data
group new { Dates = r.Dates } by r.Location into g
...
is the same as this
data.GroupBy(r => r.Location, b => b.Dates)
so if we have variable named grouper
data.GroupBy(r => {
if (grouper == "L")
return r.Location
else
return r.Dates }, b => b.Dates);
This should get you on the right track?
I have a query like below. I want to group my values by "RapId"
Result must be come like this:
RaporId 1, List of UserId 15,24,23
RaporId 2, List of UserId 18,45,57
var sorgu = (from ra in Model1
join me in Model2
on ra.RapId equals me.RapId
select new
{
RapId = ra.RapId,
UserId= ra.RaportorId,
})
.GroupBy(x=>x.RapId )
.SelectMany(x => x)
.ToList();
var results = sorgu.GroupBy(p => p.RapId , p => p.UserId,
(key, g) => new { RapId = key, UserId= g.ToList() });
I get an error like this
> Error 39 Cannot convert lambda expression to type
> 'System.Collections.Generic.IEqualityComparer<AnonymousType#1>'
> because it is not a delegate type
What's wrong with this query?
Compiler thinks you are trying to use this overload: But you are passing a lambda expressions instead of IEqualityComparer.I think you just need to remove p => p.UserId :
var results = sorgu.GroupBy(p => p.RapId,
(key, g) => new { RapId = key, UserId= g.ToList() });
I have a SQL Query
select Firma.Name as companyName,
Taetigkeit.Taetigkeit as skillName,
SUM(Zeit) as time
from Zeiterfassung
inner join Firma On ZEiterfassung.FirmenID = Firma.ID
inner join Taetigkeit on Zeiterfassung.TaetigkeitID = Taetigkeit.ID
group by Taetigkeit, Firma.Name
order by Firma.Name
And want to "translate" it to linq. Here is what I tried:
var query = db.Zeiterfassung
.Where(x => x.Firma.ID == x.FirmenID && x.TaetigkeitID == x.Taetigkeit.ID)
.GroupBy(x => x.Taetigkeit.Taetigkeit1)
.Select(x => new Evaluation() { skillName = x.Key, time = x.Sum(y => y.Zeit), //skillName = x.Sum(x => x.Zeit), })
.OrderBy(x => x.skillName);
I dont know who to solve this with joins and the group by because all the time when i do a groupBy i cant access the other members.
From data you provided, I think query should look like
from z in db.Zeiterfassung
join f in db.Firma on z.FirmenID equals f.ID
join t in db.Taetigkeit on z.TaetigkeitID equals t.ID
select new { f.Name, t.Taetigkeit, z.Zeit) into x
group x by new { x.Taetigkeit, f.Name } into g
select new {
CompanyName = g.Key.Name,
SkillName = g.Key.Taetigkeit,
Time = g.Sum(i => i.Zeit)
}
Or with navigation properties:
db.Zeiterfassung
.Select(z => new { z.Zeit, z.Taetigkeit.Taetigkeit1, z.Firma.Name })
.GroupBy(x => new { x.Taetigkeit1, x.Name })
.Select(g => new Evaluation {
companyName = g.Key.Name,
skillName = g.Key.Taetigkeit1,
time = g.Sum(y => y.Zeit)
});