LINQ query to select specific data - c#

I'm trying to write the query that will return only the specific information that I need to display in the view.
I have the following code:
var companiesWithResponsibleUser = from company in ctx.Companies
join user in ctx.Users on company.ResponsibleUserId equals user.Id
group new { company, user } by company.Id into g
select new
{
company = g.Select(t => t.company),
user = g.Select(t => t.user)
};
However this one returns the full data from both tables, which is very slow. I only need company name, address from company table and responsible user ID and full name from user table.
How can I rewrite this query so that it only populates these two objects with the data I want?

Following should help you:
var companiesWithResponsibleUser = from company in ctx.Companies
join user in ctx.Users on company.ResponsibleUserId equals user.Id
group new { company, user } by company.Id into g
select new
{
companyname = g.company.CompanyName
address= g.company.Address,
userid = g.user.UserId,
fullname= g.user.FullName
};
Please note that I haven't tested this.

I am not so sure but you can try this:
var companiesWithResponsibleUser = (from company in ctx.Companies
join user in ctx.Users on
company.ResponsibleUserId equals user.Id
select company.CompanyName,company.Address,user.Userid,user.UserFullName).ToList();
var Res = (from x in companiesWithResponsibleUser
group x by new
{
x.CompanyName,
x.Userid
} into g
select new {g.key.CompanyName, g.Address,g.key.Userid,g.UserFullName}).ToList();
You can add this part if error occur g.Address
x.CompanyName,
x.Userid,
x.Address
if field does not exists in select then user g.key.Address

Related

SQL Server query to C# Linq

I'm currently having a rough time converting my SQL query to LINQ for a school project I'm using WPF and Entity Framework
here is my SQL query (working exactly as I expect)
select IngrediantName,sum(IngrediantQuantity) as Quantity, IngrediantMeasurementUnit from Users
join Shopping_List
on Users.UserID = Shopping_List.ShoppingListID
join List_Item
on List_Item.ShoppingListID = Shopping_List.ShoppingListID
join Ingrediant
on Ingrediant.IngrediantID = List_Item.IngrediantID
where Users.UserID = 1
group by IngrediantName,IngrediantMeasurementUnit
Here is the query that I have so far
var query = from user in dbContext.Users
join shoppingList in dbContext.ShoppingLists on user.UserId equals shoppingList.UserId
join listItem in dbContext.ListItems on shoppingList.ShoppingListId equals listItem.ShoppingListId
join ingrediant in dbContext.Ingrediants on listItem.IngrediantId equals ingrediant.IngrediantId
where currentUserNumber == user.UserId
select new
{
name = ingrediant.IngrediantName,
quantity = ingrediant.IngrediantQuantity,
unit = ingrediant.IngrediantMeasurementUnit,
};
Here is what i try so far
var query = from user in dbContext.Users
join shoppingList in dbContext.ShoppingLists on user.UserId equals shoppingList.UserId
join listItem in dbContext.ListItems on shoppingList.ShoppingListId equals listItem.ShoppingListId
join ingrediant in dbContext.Ingrediants on listItem.IngrediantId equals ingrediant.IngrediantId
where currentUserNumber == user.UserId
group ingrediant by ingrediant.IngrediantQuantity into x
select new
{
name = x.GroupBy(x => x.IngrediantName),
quantity = x.Sum(x => x.IngrediantQuantity),
unit = x.GroupBy(x => x.IngrediantMeasurementUnit),
};
this one return the following error wiches doesn't tell much
Argument type 'System.Linq.IQueryable1[System.Linq.IGrouping2[System.String,Microsoft.EntityFrameworkCore.Query.TransparentIdentifierFactory+TransparentIdentifier2[Microsoft.EntityFrameworkCore.Query.TransparentIdentifierFactory+TransparentIdentifier2
If someone could point me in the right direction I would appreciate it, if you need more info I will provide it for sure
Thanks
UPDATE
I got this working here the answers to the question for anyone else
var query =
from user in dbContext.Users
join shoppingList in dbContext.ShoppingLists
on user.UserId equals shoppingList.UserId
join listItem in dbContext.ListItems
on shoppingList.ShoppingListId equals listItem.ShoppingListId
join ingrediant in dbContext.Ingrediants
on listItem.IngrediantId equals ingrediant.IngrediantId
where currentUserNumber == user.UserId
group ingrediant by new { name = ingrediant.IngrediantName, unit = ingrediant.IngrediantMeasurementUnit } into x
select new
{
name = x.Key.name,
quantity = x.Sum(x => x.IngrediantQuantity),
unit = x.Key.unit,
};
if you look at the group line
group ingrediant by new { name = ingrediant.IngrediantName, unit = ingrediant.IngrediantMeasurementUnit } into x
from my understanding you use the new to create a new selector then you can use x.key.name and x.key.unit where name and unit are simply some variable

LINQ multiple joins with a Group By not Working

After trying a lot i couldn't get this to work
I have below query:
var query = from citiez in db.cities
join site in db.sites on citiez.city_id equals site.city_id
join ords in db.orders on site.site_id equals ords.site_id
group site by site.site_id into grouped
select new {
sit = grouped.Count(),
cits = grouped.FirstOrDefault().orders
.Where(o => o.site.city.city_name == city)
};
var list = query.ToList();
It works fine but gives Circular reference error.
I have searched it but couldn't get this to work in my case
What i am trying to do in SQL is:
SELECT s.site_id, COUNT(o.order_id) TotalOrders
FROM city c
INNER JOIN site s ON c.city_id = s.city_id
INNER JOIN dbo.[order] o ON s.site_id = o.site_id
WHERE c.city_id = 4
GROUP BY s.site_id
The Query returns the desired result in SSMS.
EDIT
This is my Controller Action code:
public ActionResult draw_chart(string city)
{
var query = from citiez in db.cities
join site in db.sites on citiez.city_id equals site.city_id
join ords in db.orders on site.site_id equals ords.site_id
group site by site.site_id into grouped
select new
{
sit = grouped.Count(),
cits = grouped.FirstOrDefault().orders
.Where(o => o.site.city.city_name == city)
};
var list = query.ToList();
return Json(list, JsonRequestBehavior.AllowGet);
}
Any help would be much Appreciated.
Try this one your controller action. you will get site id and orders for site
public ActionResult draw_chart(string city)
{
var query = from citiez in db.cities
join site in db.sites on citiez.city_id equals site.city_id
join ords in db.orders on site.site_id equals ords.site_id
where citiez.city_name == city
group site by site.site_id into grouped
select new
{
siteId = grouped.Key,
ordersforsite = grouped.Count(),
};
var list = query.ToList();
return Json(list, JsonRequestBehavior.AllowGet);
}
That Linq doesn't look like the SQL you showed and most of the time you don't need to use JOIN (provided you have a good database design with relations setup). Based on your SQL you can use a Link query like this:
var result = db.Orders
.Where(o => o.City_id == 4)
.GroupBy(o => o.Site.Site_id)
.Select(g => new {
Site_id = g.Key,
TotalOrders = g.Count
});
What you intend can be expressed in this query:
var query = from citiez in db.cities
where citiez.city == city
from site in citiez.sites
select new {
sit = site.orders.count,
cits = site.orders
};
That would give you the orders for each site.

linq query using joins and aggregate functions

I want to write a linq query which retrieves the data in the following format.
Assume that there are two tables - Department and Employee
Department
Dept_id| Manager_id
Employee
Emp_id| Dept_id| Emp_data
The relationship between Department and Employee table is one to many. The Department table also stores the manager employee id in that particular department. So Manager_id is nothing but the employee_id.
Now I want to get the data as follows
Dept_id, Manager_id, Emp_data(data of Manager_id), Count(employees in that department)
If I do the join on two tables i can get data of Manager but unable to get the count of all employees in that department. Any help would be appreciated.
You could do something like this:
var result=
(
from dep in db.Department
join emp in db.Employee
on dep.Manager_id equals emp.Emp_id
select new
{
dep.Dept_id,
emp,
NumberOfEmp= db.Employee.Count(c=>c.Dept_id==dep.Dept_id)
}
).ToList();
Where db is the linq data context
You could do a group join. If you have a preferred handcoded SQL statement that you would like to be generated from your LINQ query. You may want to experiment a bit with different formats to see which one allows you to generate the "best" SQL.
var result = from d in context.Departments
join e in context.Employees on d.dept_id equals e.dept_id into g
select new {
dept_id = d.dept_id,
manager_id = d.manager_id,
manager_data = g.Single(x => x.emp_id == d.manager_id).emp_data,
employee_count = g.Count()
};
or
var result = from d in context.Departments
join e in context.Employees on d.dept_id equals e.dept_id into g
from m in g where m.emp_id == d.manager_id
select new {
dept_id = d.dept_id,
manager_id = d.manager_id,
manager_data = m.emp_data,
employee_count = g.Count()
};

What is the best way to return an entity with EF5.0?

I write this little part of code
var query = from u in context.Users
join ui in context.UserIdentifiers on u.id equals ui.user_fk
where ui.identifier_value == identifier
select new User = u;
This code is wrong because of the last line select new User = u;
So I wrote this
var query = from u in context.Users
join ui in context.UserIdentifiers on u.id equals ui.user_fk
where ui.identifier_value == identifier
select new User
{
id = u.id,
first_name = u.first_name,
last_name = u.last_name
};
return query.First();
I don't like this code because I need to map all my variables manually: id = u.id, first_name = u.first_name, last_name = u.last_name. What if I forgot one or I modify my entity and I forget to update this part of code. What if I get an entity with more than 3 variable. I'm looking for a better way to write this. Could you help me?
if User is an entity type:
var query = from u in context.Users
join ui in context.UserIdentifiers on u.id equals ui.user_fk
where ui.identifier_value == identifier
select u;
return query.FirstOrDefault();
If not, then you have to map:
select new User
{
id = u.id,
first_name = u.first_name,
last_name = u.last_name
};
or use
query.ToList().Select(u => new User(u)).FirstOrDefault()
and implement a suitable constructor.
The problem you have are the different classes, you select table Users, but you work with class User.
So if it is possible for you, just use your class Users. Then you can select your Entity directly in your query:
var query = from u in context.Users
join ui in context.UserIdentifiers on u.id equals ui.user_fk
where ui.identifier_value == identifier
select u;
But i also know that this is not always possible, in some projects we have similar issues. There is no integrated possibility to cast your classes automatically.
Nevertheless there is a tool called Automapper with which you can cast your classes. For example you can Map two classes together like this:
Mapper.CreateMap<Users, User>();
The good thig about this is, that you don't have to tell automapper which properties to map if they have the same name in both classes.
Then you can just map automatically all properties like this:
var user = Mapper.Map<User>(query.First());

Including objects from join in query result

Imagine a simple Entity Framework query with a context generated from the database such as:
var q = from a in context.Accounts
join c in context.Contracts
on a.Id equals c.AccountId
select new CustomAccount {
Id = a.Id,
Name = a.Name,
...
Contracts = //How do I easily populate the related contracts?
};
The query looks for accounts and joins to contracts. The relationship is not enforced in the database (I can't change the schema) so I can't use navigational properties. Is there an easy way that I can populate the related objects?
Just use a group by clause. Something like this (untested):
var q = from a in context.Accounts
join c in context.Contracts on a.Id equals c.AccountId
group a by new { a.Id, a.Name, a.Etc } into g
select new CustomAccount
{
Id = g.Key.Id,
Name = g.Key.Name,
Etc = g.Key.Etc,
Contracts = g.SelectMany(x => x.Contracts)
};
I'm not sure if I understand correctly but you can execute a query that return anonymous type objects
EDIT : you can create a custom class to hold the data member of your result and return in linq result.
EDIT : using group by on account name (e.g)
var q = from a in context.Accounts
join c in context.Contracts
on a.Id equals c.AccountId
group a by new { a.Name } into g
select new AccountContracts
{
AccountName = g.Key.Id, // Account name
Contracts = g.SelectMany(x => x.Contracts)
};

Categories

Resources