I have a table say Category with the following fields:
cat_id, cat_name and Cat_desc
I also have another table product with the following fields:
pro_id, cat_id, pro_name and pro_desc, is_finished
Ordinarily, if I select a category with Linq to sql, it returns the category with all the associated products.
But I want to select a category but the products returned should be only product with is_finished value that is true.
any suggestion/code sample will be appreciated.
You need to join the tables:
select * from product p
left join Category c on c.cat_id = p.cat_id
where c.cat_name = 'yourcategory' and p.is_finished = 1
In linq to SQL:
var query = from product in products
join category in categories on category.cat_id = product.cat_id
select new { product.is_finished = true, category.cat_name = "yourcategory" };
This is probably the wisest way to do what you're asking:
var query = from product in products
select new {
product,
finishedCategories = product.categories.Where(c => c.is_finished)
};
This creates an anonymous type that has the data you're looking for. Note that if you access .product.categories you'll still get all of that product's categories (lazily-loaded). But if you use .finishedCategories you'll just get the categories that were finished.
Related
I am having problems in writing a LINQ for calculating average value based on not directly referenced column.
Provide background and tell us what you've already tried.
I have following tables, now I want average marks based on category and subcategory, But fetching it through TopicId(FK) in Result table is going to be a big task.
(I tried and couldn't figure out how to do it)
Image having tables
How Can I get average marks for Category and subcategory?
This is the SQL query that you need:
select
c.Id as CategoryId,
c.CategoryName,
sc.Id as SubCategoryId,
sc.SubCategoryName,
AVG(r.Marks) as Average
from Result r
join Topic t on r.TopicId = t.Id
join SubCategory sc on t.SubCategoryId = sc.Id
join Category c on sc.CategoryId = c.Id
group by c.Id, c.CategoryName, sc.Id, sc.SubCategoryName
And this is the same with LINQ query syntax:
using (var db = new TopicContext())
{
// build the query
var query =
from r in db.Result
join t in db.Topic on r.TopicId equals t.Id
join sc in db.SubCategory on t.SubCategoryId equals sc.Id
join c in db.Category on sc.CategoryId equals c.Id
group r by new { c.Id, c.CategoryName, SubCategoryId = sc.Id, sc.SubCategoryName } into gr
select new
{
CategoryId = gr.Key.Id,
CategoryName = gr.Key.CategoryName,
SubCategoryId = gr.Key.SubCategoryId,
SubCategoryName = gr.Key.SubCategoryName,
Average = gr.Average(x => x.Marks)
};
// ToList() method executes the query, so we get the result on that line of code
var result = query.ToList();
}
If you have an existing database you can use EF Core to generate your own dbContext (in my example this is TopicContext class) with the help of Scaffold-DbContext command. You can find an example of this command on that page. To use this command you should install Microsoft.EntityFrameworkCore.Tools nuget package along with Microsoft.EntityFrameworkCore.SqlServer.
I have a fairly complex query that I'm trying to implement via Linq. I'm struggling to find a way to:
Order by a select return (the IFNULL result that's selected is used in the group by)
Get all the distinct results a group by in sql would
How can I reproduce this query via Linq?
select
company.id
IFNULL(employee.team_name, employee.name) AS team_name
FROM company
INNER JOIN branch on branch.parent_company_id = company.uuid
INNER JOIN map_employee_to_branch on map_employee_to_branch.machine_uuid = branch.uuid
INNER JOIN employee on employee.id = map_employee_to_branch.employee_id
where company.name = "Whatever" AND map_employee_to_branch.isActive = true
GROUP BY map_employee_to_branch.employee_id, company.id
ORDER BY company.id, employee.title, team_name, employee.name
I'm going to assume your inner joins are handled by your navigation property mappings, and I'm making some assumptions about your entity property names.
(from company in context.Companies
where company.name = "Whatever"
from branch in company.Branches
from m in branch.MapEmployeeToBranches
where m.IsActive
let employee = m.Employee
select new {
companyId = company.id,
employeeId = employee.id
employee.title,
teamName = employee.team_name ?? employee.name,
employee.name
} into projection
orderby projection.id, projection.title, projection.teamName, projection.name
group new { projection.companyId, projection.teamName }
by new { projection.employeeId, projection.companyId }
Is it possible to create the below written dapper query with returntype as IEnumerable<dynamic> as I do not have Product & Supplier POCO.
IEnumerable<Product> products = sqlConnection
.Query<Product, Supplier, Product>(
#"select Products.*, Suppliers.*
from Products join Suppliers
on Products.SupplierId = Suppliers.Id
and suppliers.Id = 2",
(a, s) =>
{
a.Supplier = s;
return a;
});
What if my sql query was something as below, how would my dapper query be with returntype of IEnumerable<dynamic>
select Products.ProductId,Products.ProductName,Products.ProductCategory, ProductPrice.Amount,ProductPrice.Currency
from Products join ProductPrice
on Products.ProductId = ProductPrice.ProductId
All help is sincerely appreciated.
Thanks
Yes you can map the result of your queries to a list of dynamic objects (documentation here).
const string sql = #"select Products.ProductId, Products.ProductName, Products.ProductCategory, ProductPrice.Amount, ProductPrice.Currency
from Products join ProductPrice
on Products.ProductId = ProductPrice.ProductId";
IEnumerable<dynamic> products = sqlConnection.Query(sql);
In your first example you are doing multi mapping which maps each table row onto 2 objects instead of one (Product and Supplier) that are then linked by reference before the product is returned. I don't think you could do this with dynamic objects, because Dapper would have no way of knowing how to divide the columns among them. You could confirm this with a test, replacing generic parameters <Product, Supplier, Product> with <dynamic, dynamic, dynamic>.
Skipping the multi-mapping would just mean that the dynamic objects returned would contain both Product and Supplier properties, which might not be a problem for you.
I have a Category table with a tree structure (Id,MasterId)
I'd like to select all products that belong to a Category and all Child Categories.
Today I use this SQL Query which works, but I'd like to add pagination and that would be easier with a pure LINQ query. I use Entity Framework 4.
#Count int = 100,
#CategoryId int
with mq as
(
select c.Id as parent, c.Id as child
from dbo.Categories c
where c.Id = #CategoryId
union all
select q.child, c.Id
from mq q
inner join dbo.Categories c on q.child = c.MasterId
)
select top (#Count) P.* from Products P
inner join ProductToCategory PC ON(PC.ProductId = P.Id)
where PC.CategoryId in (
select child from mq
)
and P.PublishStatus = 1
order by P.PublishedDate DESC;
Any ideas how to get a nice LINQ query on this with pagination (current page, number of products per page, total product count)?
This is recursive / hiearchical query with table expression. EF does not provide support for such queries. If you want to receive data by single roundtrip to DB you must wrap it in stored procedure and import that procedure to your entity framework model.
Paging in SQL is also possible when using table expressions and ROW_NUMBER().
there is an idea. i haven't tested it, so dont blame if it doesn't work :P
var ids = context.TreeItems.Where(x => x.Id == parentId).Select(x => (int?)x.Id);
var tmp = ids;
while (true)
{
IQueryable<int?> localIds = tmp;
var subIds = context.TreeItems.Where(x => ids.Contains(x.ParentId)).Select(x => (int?)x.Id);
if (subIds.Any())
{
tmp = subIds;
ids = ids.Union(subIds);
}
else
break;
}
var allSubItems = context.TreeItems.Where(x => ids.Contains(x.Id));
I have two tables Orders and Products where Orders has a ProductID as a forgin key,
I would like to select all products, if a product has orders i would like to select the one with the highest distance field.
thanks,
Your question seems a bit unclear. However, I am assuming that your orders table has a 'distance' column. You would like to select all products with the order that has the highest distance value.
var products = from p in db.Products
select new
{
ProductID = p.ProductID,
ProductName = p.ProductName,
HighestDistanceOrder = p.Orders.OrderByDescending(o => o.Distance).FirstOrDefault()
};
If you wanted the value of highest distance and not the entire order, then
var products = from p in db.Products
select new
{
ProductID = p.ProductID,
ProductName = p.ProductName,
HighestDistance = p.Orders.Max(o => o.Distance)
};
Hope that helps.
Matrich