I have a class:
public class CustomerEmailAlert
{
public string EmailId { get; set; }
public string Interest1 {get;set;}
public string Interest2 {get;set;}
}
The result from sql is something like this:
+---------------+-----------+-----------+
| Email | Interest1 | Interest2 |
+---------------+-----------+-----------+
| abc#gmail.com | Burrito | Apple |
| abc#gmail.com | Pizza | Milk |
| abc#gmail.com | Apple | Burrito |
| def#gmail.com | Milk | Banana |
+---------------+-----------+-----------+
I have mapped the result using Dapper to List<CustomerEmailAlert>
List<CustomerEmailAlert>= con.Query<CustomerEmailAlert>("getalerts", commandType: CommandType.StoredProcedure).ToList();
My question is: How do I group Customers by Email so that the email they receive contains their interests (they should receive only 1 copy of email)
I have tried this: Group by in LINQ
You could group this way:
var result= from e in list
group new {e.Interest1,e.Interest2} by e.Email into g
select new {Email=g.Key, Interests=g.ToList()};
Related
I have this Linq to Entities (EF Core) query which looks like below
var query = (from p in db.Samples
join q in db.Items on p.Id equals q.SampleId
Where p.active = IsActive and p.Id = GivenId
group new
{
p.Name,
p.Address,
p.Marks,
p.LocationId,
q.EmailId,
q.Grade
}
by new
{ q.Grade }
into data
select new DataSummary()
{
UserName = data.Name,
Grade = data.Min(x => x.Grade),
Email = data.Min(x => x.Email,
Total = data.Sum(x => x.Marks)
}.ToList()
Now I have a constant List of Hashset of Grades and Location that looks like this:
public List<(HashSet<string> Grades, HashSet<Location> Loctions)> LocationGrades => new()
{
(new() { "A", "B" }, new()), // Includes all location
(new() { "C"}, new(){
Location.Boston, //Location is Enum
Location.Maine
}
}
I want to get the data where if the student has grade A or B include all location and if the student has grade C only include Boston and Maine.
Is it possible to integrate this within the LINQ to Entities query?
Sample Table
| ID | Name | Address | Marks | LocationId |
|-----|-------|---------|-------|-------------|
| 234 | Test | 123 St | 240 | 3 (Maine) |
| 122 | Test1 | 234 St | 300 | 5 (Texas) |
| 142 | Test1 | 234 St | 390 | 1 (Boston) |
Items Table
| ID | SampelId | Grade | Email |
|----|----------|-------|-------|
| 12 | 234 | A | a.com |
| 13 | 122 | C | b.com |
| 14 | 142 | C | c.com |
So, In the table above I shouldn't get Texas row but get Boston row as they both have Grade C but Texas does not exist in the HashSet combo.
Okay, now I got it. You have to add dynamic ORed constraints to the query based on a given list of elements. This is a little tricky, because AND can be done with using multiple .Where() statements, but OR not. I did something similar recently against CosmosDB by using LinqKit and the same should also work against EF.
In your case you probably of to do something like this:
...
into data
.WhereAny(grades, (item, grade) => item.Grade == grade)
select new DataSummary()
...
I think the given example doesn't match your exact case, but it allows you to define multiple ORed constraints from a given list and I think this is the missing part you're searching. Take care to use within the lambda method only definitions which are also supported by EF core. The given inner enumeration (in this example grades) will be iterated on the client side and can be dynamically build with everything available in C#.
Please be kind to a LINQ dummy...
Say I have 8 rows data like this:
+-------------------+
| ID WORKTYPEDESC|
+-------------------+
| 1 plumber |
| 1 carpenter |
| 1 electrician |
| 2 juggler |
| 2 mime |
| 3 writer |
| 3 actor |
+-------------------+
As an 8-item IList<Worktype> collection where Worktype looks like
public class Worktype
{
public int Id { get; set; }
public string WorktypeDesc { get; set; }
}
And what I want is to aggregate by Id to get a list with 3 Worktypes, each with a WorktypeDesc being a sorted, semicolon-delimited list, like this:
+-------------------------------------+
| ID WORKTYPEDESC |
+-------------------------------------+
| 1 carpenter;electrician;plumber |
| 2 juggler;mime |
| 3 actor;writer |
+-------------------------------------+
??
Just group by Id, use string.Join to aggregate within each group.
IEnumerable<Worktype> source = ...;
var query = source.GroupBy(
x => x.Id,
(id, g) => new Worktype
{
Id = id,
WorktypeDesc = string.Join(";", g.Select(x => x.WorktypeDesc).OrderBy(x => x))
});
I have a model
public void CarModel()
{
public string Name {get; set;}
public string Brand {get; set;}
public string Color {get; set;}
}
And I have a database table called Vehicles
id | Name | Brand | Color | ...
---+---------+----------+--------+--------
1 | carA | A | Green |
2 | carB | C | Red |
3 | carC | D | Orange |
4 | carA | C | White |
And then I wanted to find this one specifically
---+---------+----------+--------+--------
3 | carC | D | Orange |
Without knowing the ID just by knowing the Name, Brand & Color.
I want to fetch all the entries if that's the correct term using SQL syntax.
Here is solution with Linq syntax:
var vehicles = _db.Vehicles.Where(r=>r.Name=="carC" && r.Brand="D" && r.Color=="Orange").ToList();
You can try below -
select * from Vehicles
where name='carC' and brand='D' and color='Orange'
everyone!
I've just faced a problem with timing out in my LINQ query.
I have 3 tables: Work, Projects and Subprojects.
Projects:
+--------+
| Id |<--+<--+
| Name | | |
+--------+ | |
SubProjects: | |
+--------+ | |
+->| Id | | |
| | Name | | |
| | ProjId |---+ |
| +--------+ |
| Work: |
| +------------+ |
| | Id | |
| | Type | |
| | ProjId |---+
+--| SubProjId | (nullable)
+------------+
I need to create a report based on Subprojects:
Group by subproject Id,
if subproject Id is null -> group by project Id
I've solved it by making two queries and then merging them, but when sometimes it times out.
I was doing it with
result1.AddRange(result2);
because
var temp = result1.Concat(result2);
is throwing an Exception:
Internal .NET Framework Data Provider error 1004, 0, Unresolvable Var used in Command: VarType=Computed, Id=2090.
Can somebody help me with creating it in one query?
I'm not sure what your code looks like so this might not be perfect but you could try something like this:
var result = from work in works
group work by work.SubProjId ?? work.ProjId into groupedWorks
select groupedWorks.ToList();
or
var result = works.GroupBy(work => work.SubProjId ?? work.ProjId).ToList();
try this query
var itemlist =contex.Work.where(x=>x.SubProjId !=null).Groupby(x=>x.SubProjId).Concat(Contex.Work.where(x=>x.SubProjId ==null).Groupby(x=>x.ProjId)).ToList();
I'm guessing this is what you need:
var groups = from work in ctx.Works // the work table
group work // we want to group whole work "rows"
// we are grouping by project id and subproject id
by new { ProjId = work.ProjId, SubProjId = work.SubProjId }
into g // and we are calling the grouping 'g'
select g; // select the group
// example of doing something with the groupings
foreach (var group in groups)
{
var key = group.Key; // gets a { ProjId, SubProjId } tuple
foreach (var work in group)
{
// each work is a row in the Work-table
}
}
First Table
+--------+------------+-------+
| type | variety | price |
+--------+------------+-------+
| apple | gala | 2.79 |
| apple | fuji | 0.24 |
| apple | limbertwig | 2.87 |
| orange | valencia | 3.59 |
| orange | navel | 9.36 |
| pear | bradford | 6.05 |
| pear | bartlett | 2.14 |
| cherry | bing | 2.55 |
| cherry | chelan | 6.33 |
+--------+------------+-------+
Second Table
+--------+----------+
| type | minprice |
+--------+----------+
| apple | 0.24 |
| cherry | 2.55 |
| orange | 3.59 |
| pear | 2.14 |
+--------+----------+
select type, min(price) as minprice
from fruits
group by type;
The first table is and example of the data that I have and the second table is what I want to get from the first.
I am using GenericRepository/UnitOfwork to get the data from repository.
repository.fruitRepository.Get().GroupBy(m => m.type);
But I can only get the type field but I want to get more fields.
Do I need to use a select clause before groupby? If yes, how can I select more fields?
The GroupBy method returns more data, but it's returned as an enumerable... you may be able to pull what you want out of it with a Select after the GroupBy...
repository.fruitRepository.Get()
.GroupBy(m => m.type)
.Select(m => new { type = m.Key, minPrice = m.Min(f => f.Price) });
Or if you prefer a LINQ statement:
var result = from x in repository.fruitRepository.Get()
group x by x.type into typeGroup
select new
{
type = typeGroup.Key,
minPrice = typeGroup.Min(item => item.Price)
};