How to use LINQ to retrieve child collection - linq

Starting here:
public class Customer
{
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public IList<Order> Orders { get; set; }
}
public class Order
{
public int OrderID { get; set; }
public int CustomerID { get; set; }
}
What would be the linq query that you write to retrieve all Orders from all Customers?
Something to the effect of:
IList<Order> orders = new List<Order>();
foreach (Customer c in Customers)
{
orders.Union(c.Orders);
}
I tried the following but it throws an "nhibernate collection was not an association" exception:
var orders = from c in Customers
select c.Orders;
I know I'm missing something, but I can't find a way to achieve this in linq.

var orders = from c in db.Customers
from o in c.Orders
select o;
Or
var orders = db.Customers.SelectMany(c => c.Orders);
Will it work in linq for nhibernate? I don't know.

Make sure your foreign key constraint is setup properly from [Order].[CustomerID] to [Customer].[ID] in the database.

Related

LINQ: How to filter collection by data in related table

I have two Entity Framework Core entities:
public class JobOrder {
public int Id { get; set; }
public string JobTitle { get; set; }
public string Status { get; set; }
...
public IEnumerable<JobOrderUser> JobOrderUsers { get; set; }
}
public class JobOrderUser {
public int AppUserId { get; set; }
public AppUser User { get; set; }
public int JobOrderId { get; set; }
public JobOrder JobOrder { get; set; }
}
The second one is a join table used for a many-to-many between the JobOrder and User tables but I don't need to drill to the User table for this.
I want to get a collection of JobOrders that have an association with a specific user. In SQL, I would write something like this:
select distinct
a.*
from
JobOrders a
join JobOrderUser b on a.JobOrderID = b.JobOrderId
where
b.AppUserId = someId
How do I do that using LINQ method syntax?
If your entities are set up correctly, and their relationships are intact, you could load the JobOrderUsers while querying for a JobOrder and then filter by a user. Something like
JobOrder.Include(t => t.JobOrderUsers).Where(t => t.JobOrderUsers.Any(x => x.User.Id == SomeId));
You can also use the below query using join and Select the required columns data in a jobOrdersDto class. For that, you have to inject the _jobOrdersRepository and _jobOrderUserRepository repositories to your service where you are calling the required method.
var result = (from jobOrders in _jobOrdersRepository.GetAll()
join jobOrderUser in _jobOrderUserRepository.GetAll() on jobOrders.JobOrderID equals jobOrderUser.JobOrderId
where
(jobOrderUser.AppUserId == someId)
select new jobOrdersDto
{
}
Your Service class:
public class YourService
{
private readonly IRepository<jobOrders> _jobOrdersRepository;
private readonly IRepository<jobOrderUser> _jobOrderUserRepository;
public YourService(
IRepository<jobOrders> jobOrdersRepository, IRepository<jobOrderUser> jobOrderUserRepository)
: base()
{
_jobOrdersRepository = jobOrdersRepository;
_jobOrderUserRepository = jobOrderUserRepository;
}
}

What would be the best way to get all the products in all the child categories of a selected main category?

What would be the best way to get all the products in all the child categories of a selected main category?
This is my Class File Structure:
public partial class Category
{
public int Id { get; set; }
public string Name { get; set; }
public int ParentCategoryId { get; set; } //reference to Id
public ICollection<Category> _subcategories;
}
public partial class ProductCategory
{
public int Id { get; set; }
public int ProductId { get; set; }
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
public virtual Product Product { get; set; }
}
public partial class Product
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<ProductViewMap> _productViewmap;
}
public class ProductViewMap
{
public int ProductId { get; set; }
public int ProductViewCount { get; set; }//indicated how many times product has been viewed means most popular product.
public virtual Product Product { get; set; }
}
This is what i have tried:
//List to hold all Category Ids of Parent Category Id say for eg:1
List<int> categoryChildList = new List<int>();
var data = (from temp in context.Category
where temp.ParentCategoryId == parentCategoryId
select new { CategoryId = temp.Id });
if(data.Count() > 0)
{
foreach (var cat in data)
{
int _cat = Convert.ToInt32(cat.CategoryId);
categoryChildList.Add(_cat);
}
var tmpList = (from p in Context.ProductCategory
join m in context.Product on p.ProductId equals m.Id
join n in context.ProductViewMap on m.Id equals n.ProductId
where categoryChildList.Contains(p.CategoryId)
select m).ToList();
Here error is coming:
Object reference not set to instance of object.**
When i am removing this line then everything works fine:
join n in context.ProductViewMap on m.Id equals n.ProductId
any help would be greatly appreciated.
Sql fiddle which contain sample records:http://www.sqlfiddle.com/#!3/bde6b
If Input is :Computer(parentCategoryId:1) then output is as below
Final output:
ProductId ProductName
1 hp
2 compaq
3 lenovo
If all you're trying to do is to grab the Product records, then using the Extension Method syntax you could do it this way:
var products = context.ProductCategory.Where(pc => pc.Category.ParentCategoryID != null && pc.Category.ParentCategoryID == parentCategoryID)
.Select(pc => pc.Product)
.Distinct()
.ToList()
.OrderBy(p => p.ProductViewMap.Max(pvm => pvm.ProductViewCount);
All of the joins will be taken care of by the SQL query generated by LINQ to Entities.

Fetch single value with linq projection query without using FirstOrDefualt

I am using Entity Framework and this is my view model:
public class UserDetailsModel:CityModel
{
public int Id { get; set; }
public string Fullname { get; set; }
}
public class VendorInCategoryModel
{
public int CategoryId { get; set; }
public int VendorId { get; set; }
public virtual CategoryMasterModel CategoryMaster { get; set; }
public virtual UserDetailsModel UserDetails { get; set; }
}
public class CategoryMasterModel
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
This is my query to fetch vendor details along with category details of particular vendor say v001:
UserDetailsModel workerDetails = context.UserDetails.
Where(d => d.Id == _vendorId).
Select(d => new UserDetailsModel
{
Id = d.Id,
Fullname = d.Fullname,
CategoryId = d.VendorInCategory.Select(v => v.CategoryId).FirstOrDefault(),
}).SingleOrDefault();
Here I have used FirstOrDefault to fetch categoryId (that is single value)
But I don't want to use FirstOrDefault as I have used in so many queries and it is giving me wrong output in some cases. So that the reason why I don't want to use FirstOrDefault.
When I have written SingleOrDefualt in place of FirstOrDefault it is throwing me error
that use FirstOrDefault.
So how to overcome this? Can anybody please help me?
It looks like maybe your outer select is capable of returning multiple results (e.g. if there are more than one UserDetailsModel with the same Id). If it returns multiple results then your call to .SingleOrDefault() will throw an exception as it expects only a single result or no results. See LINQ: When to use SingleOrDefault vs. FirstOrDefault() with filtering criteria for more details.

How to apply Nested Select using Linq

I'm working with nested select and seems like what i am doing is not correct!.
I'm trying to retrieve all the Topics items.
public class Employee
{
public int Id{ get; set; }
//....other fields....
//......
public IList<Topics> Interest { get; set; }
}
public class Topics
{
public int Id { get; set; } ;
public string Name { get; set; } ;
//other fields
}
employeeItems = (from _emp in employees
select new Employee
{
EmpId = _emp.mediaId,
EmpName = _emp.mediaType,
......................
Interest = (from _emp1 in employees.Interest //has few rows
select new Topic
{
Id = _emp1.Topics[0].Id, //.<int>("id"), <<<ERROR
Name = _emp1.Topics[0].Name //["name"] <<<ERROR
}).ToList()
}).ToList();
}
Interest = (from topic in _emp.Interest.SelectMany(i=>i.Topic) //has few rows
select new Topic
{
Id = topic.Id, //.<int>("id"), <<<ERROR
Name = topic.Name //["name"] <<<ERROR
})
public class Employee
{
public int Id{ get; set; }
//....other fields....
//......
public IEnumberable<Topics> Interest { get; set; }
}
Leave the property as IEnumberable and don't do .ToList() inside the query. And it seems to me your data structure is employee has multiple interests and each interest has mulitple topics, that's why I used selectmany, but you can adjust it if I'm wrong with the data.

How to get Users who only have some specific department id, Linq

I have following two entities
public class User
{
public int UserId { get; set; }
public string UserName { get; set; }
public List<Department> Departments { get; set; }
}
public class Department
{
public int DepartmentId { get; set; }
public string DepartmentName { get; set; }
public List<User> Users { get; set; }
}
As you see, relationship between two objects is M:N.
I wanna get User who only have specific department ID, in this case, How to get users using Linq?
Thanks in advance
int requiredId = ...
var usersInReqdDept = Users.Where(u => u.Departments
.Any(d => d.DepartmentId == requiredId));
If the Departments list can be null, you will need a null-check in the Where clause.
If you want to search the Departments list instead,
int requiredId = ...
var usersInReqdDept = Departments.Single(d => d.DepartmentId == requiredId)
.Users;
Of course, this will throw an exception if such a department doesn't exist.

Resources