LINQ group by ID - Distinct by order - linq

I have data in a generic list named "Assignment" as shown in the Original table. Want to group by ID and display only one record based on US-UK-India order.
The result should transform from first table to second as shown in the attached image.

Try this:
SQL like syntax.
from a in Assignments
group a by a.Id into gr select gr.FirstOrDefault()
Lambda expression:
Assignments
.GroupBy (a => a.Id)
.Select (gr => gr.FirstOrDefault ())

Try this, its works. I hope this is what you need.
var query01 = context.FirstTable
.GroupBy(p => p.ID
,(ky, el) => new { ky.Value , FirstCountry = el.Select(p => Country).Take(1)});
var Result = query01
.Join(context.FirstTable
, ul => new
{
Id = ul.Value
,Country = ul.FirstCountry.FirstOrDefault()
}
, fl => new
{
Id = (int)fl.ID
, Country = fl.Country
}
, (ul, fl) => new { fl }).ToList();

Related

How to Convert a LINQ Query Syntax to a Method Syntax? (with join and multiple selects) Issue: Where-no overloads for + 3 parameters

I am trying to understand lambda expressions with Linq but i struggle with the conversion. Below is the Linq Query syntax which works just fine.
var systemUsersPoor =
(from customer in customers
join distributor in distributors
on new { customer.Location }
equals new{ distributor.Location }
where customer.Location == "UK" &&
customer.Location==distributor.Location &&
customer.Supplier == "MoneyShits" &&
distributor.Products == "ShittyCrappyCraps"
orderby customer.Name
select new
{
customerName=customer.Name , customerLocation=customer.Location, customerSupplier=customer.Supplier,
distributorName=distributor.Name, distributorProducts=distributor.Products
}).ToList();
And then in here, i have my failed attempt to convert it into a Linq Method Syntax...All works untill the .Where statement..states that it does have no definition for my fields(.location,.Supplier) and distributor
var sysUserPoor2 = customers.Join //from customer in customers Join
(
distributors, //Join on distributors on customer.Location==distribution.Location
customer=> customer.Location, //Select the primary key (the first part of the "on" clause in an sql "join" statement
distributor =>distributor.Location, // Select the foreign key (the second part of the "on" clause)
(customer, distributor) => new //select statement
{
customerName = customer.Name,
customerLocation = customer.Location,
customerSupplier = customer.Supplier,
distributorName = distributor.Name,
distributorProducts = distributor.Products
}
)
.Where
(
customer => (customer.customerLocation == "UK") &&
(customer.customerSupplier == "MoneyShits"),
distributor => distributor.distributorProducts == "ShittyCrappyCraps",
(customer, distributor) => (customer.customerLocation == distributor.Location)
);
The query with the code below works, but i dont know how to add the rest somehow...:
.Where
(
customer => (customer.customerLocation == "UK") &&
(customer.customerSupplier == "MoneyShits")
)
Please try following.
var systemUsersPoor = customers.Join(distributors,
customer => customer.Location,
distributor => distributor.Location,
(customer, distributor) => new {customer, distributor})
.Where(x => x.customer.Location.Equals("UK") &&
x.customer.Location.Equals(x.distributor.Location) &&
x.customer.Supplier.Equals("MoneyShits") &&
x.distributor.Products.Equals("ShittyCrappyCraps"))
.OrderBy(x => x.customer.Name)
.Select(x => new
{
customerName = x.customer.Name,
customerLocation = x.customer.Location,
customerSupplier = x.customer.Supplier,
distributorName = x.distributor.Name,
distributorProducts = x.distributor.Products
}).ToList();

How to write LINQ query as one query?

I have the following query that groups locations and the average item cost and I would like to write it as one query but I cannot figure out the syntax. What LINQ do I need to do this? I have tried writing it different ways but the syntax is not correct.
var joinedData =
from r in shops
join i in items on r.shopId equals i.shopId
select new
{
Region = r.Location,
ItemCost = i.ItemCost
};
var AverageCostByLocation = joinedData
.GroupBy(m => new { m.Location})
.Select(m => new
{
Location= m.Key.Location,
AverageItemCost = m.Average(x => x.ItemCost)
});
Well, if you put first expression in parenthesis it should allow to join both expressions as they are. Also I'd probably get rid of second anonymous type for perfomance reasons (the new { m.Location} line is redundant, you might want to use .Key instead) :
var AverageCostByLocation =
(from r in shops
join i in items on r.shopId equals i.shopId
select new
{
Region = r.Location,
ItemCost = i.ItemCost
})
.GroupBy(m => m.Location)
.Select(m => new
{
Location= m.Key,
AverageItemCost = m.Average(x => x.ItemCost)
});

Replacing empty values with a default value in a Linq to Entities query

In the Linq to Entities query below I need to place a default value in the x.Number in the returned value if the query returns 0 OfficeTelephone objects. I have tried
x.Number??"555-1212" but that throws an error.
from c in Contacts
.Where(a => a.LastName.Contains("ANDUS")).Take(10)
select new
{
Id = c.Id,
OfficeTelephone = c.Telephones.Where(a=>a.TelephoneType.Name.Contains("Office")).Select(x => new { x.AreaCode, x.Number, x.TelephoneType, x.Primary })
}
I've tried something like:
from c in Contacts
.Where(a => a.LastName.Contains("ANDUS")).Take(10)
select new
{
Id = c.Id,
OfficeTelephone = c.Telephones
.Where(a=>a.TelephoneType.Name.Contains("Office"))
.Select(x => new { x.AreaCode, x.Number, x.TelephoneType, x.Primary })
.DefaultIfEmpty()}
But I'm not sure how to push a default object into the DefaultIFEmpty()
Use DefaultIfEmpty and pass a default instance with those value which you would want by default i.e. if no rows are returned.
try it like this:
Contacts.Where(a=>a.LastName.Contains("ANDUS"))
.Take(10)
.Select(x => new
{
Id = x.Id,
OfficeTelephone = x.Telephones
.Where(a=> a.Telephone.Name.Contains("Office"))
.Select(b=> new Telephone
{
b.AreaCode,
b.Number,
b.TelephoneType,
b.Primary
})
.DefaultIfEmpty(new Telephone())
});
where I've assumed that typeof(x.Telephones) == typeof(List<Telephone>)

LINQ - optional/nullable where conditions

I do have the following LINQ query, selecting movies from my database that either contain the given search string or have one or more of the tags that I give to the function.
The problem is, that if the search string or the tags parameter are empty/null, I get no movies. The desired action however, is to get all the movies, so, if one parameter is null or empty, I don't want to apply it.
How can I do that?
public IEnumerable<Group<Genre, Movie>> GetMoviesGrouped(string search, List<Tag> tags)
{
var movies = from movie in Movies
where ( movie.Name.Contains(search)) && movie.Tags.Any(mt => tags.Any(t => t.ID == mt.ID))
group movie by movie.genre into g
select new Group<Genre, Movie> { Key = g.Key, Values = g };
....
}
Just for readability, I like to do it step by step
var movies = Movies;
if (!string.IsNullOrEmpty(search))
movies = movies.Where(m => m.Name.Contains(search));
if (tags != null && tags.Any()) {
var tagIds = tags.Select(m => m.ID);
movies = movies.Where(m => m.Tags.Any(x => tagIds.Contains(x.ID));
}
var result = from movie in movies
group ...
You can do something like this to skip the check if nothing is provided:
where (string.IsNullOrEmpty(search) || movie.Name.Contains(search)) &&
(!tags.Any() || movie.Tags.Any(mt => tags.Any(t => t.ID == mt.ID)))

Access any data that is not contained in grouped element

from teamBudget in TeamBudgets
where teamBudget.TeamID == 71002
join teamBroker in TeamBrokers on 71002 equals teamBroker.TeamID
join goal in Goals on teamBroker.GlobalBrokerID equals goal.GlobalBrokerID
group goal by goal.GlobalBrokerID into g
select new
{
// TeamID=teamBroker.TeamID,
// MTDGoal=teamBudget.Sum(t => t.Budget),
RevenueMTDCurrent = g.Sum(x => x.RevenueMTDCurrent)
}
Commented part is a problem. How to access any data that is not contained in grouped element?
you need to Group multiple fields then only you can access that data.
like
var result = from i in
(from uh in db.UserHistories
where uh.User.UserID == UserID && uh.CRMEntityID == (int)entity
select new { uh.ActionID, uh.ActionType, uh.ObjectID })
group i by new { i.ActionID, i.ActionType, i.ObjectID } into g
select new { g.ActionID, g.ActionType, g.ObjectID };
Hope this will help

Resources