NHibernate QueryOver parent object - linq

I have a model with two classes :
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public List<Product> { get; set; }
}
public class Product
{
public string Name { get; set; }
public string Code { get; set; }
public decimal Amount { get; set; }
}
which is represented in two different tables in database.
How do I use QueryOver<> to query Products based on their Category and their Amount and finally select Products.
In entity framework I would write something like :
context.Categories.Where(s=>s.Id == #1)
.Select(s=>s.Products)
.Where(s=>s.Amount>12333).ToList();
OR
context.Products.Where(s=>s.**Category**.Id == #1 && s.Amount > 12333).ToList();

Firstly, you should (almost must) extend the relation from Product to Category:
public class Product
{
...
public Category Category { get; set; }
It is already in DB, so there is no reason why to hide it from the POCO entities.
Then, as stated in documentation:
16.4. Associations
We can do it like this:
var results = session
// here we get query related to Product
.QueryOver<Product>()
// here we filter Product
.And(p => p.Amount > 12333)
// here we join the Category
.JoinQueryOver(p => p.Category)
// and do some farther filtering
.Where(c => c.Id == 1)
// list of products
.List<Product>()

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.

Linq with where clause in many-to-many EF Code First object

In an MVC4 project, using code first, I have the following:
public class Course
{
public string CourseId { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public virtual Categories ICollection<Category> { get; set; }
public Course()
{
Categories = new HashSet<Category>();
}
}
public class Category
{
public string CategoryId { get; set; }
public string Name { get; set; }
public virtual Courses ICollection<Course> { get; set; }
public Category()
{
Courses = new HashSet<Course>();
}
}
Code First then rightly creates an extra table for this relation, since it is many-to-many.
My problem is when I need a list of Categories with the active Courses (IsActive==true). This here, for example, is not possible:
var categories = db.Categories.Where(x => x.Courses.Where(y => y.IsActive)).ToList();
Any input how I get a list of the categories with only the active courses?
Thanks!
This query will return all categories that have at least one course that is active:
var categories = db.Categories
.Where(x => x.Courses.Any(y => y.IsActive))
.ToList();
This query will return all categories whose courses are all active. If, for example, a category has two courses and one of the courses is inactive, that category will be excluded from the query:
var categories = db.Categories
.Where(x => x.Courses.All(y => y.IsActive))
.ToList();

What is the standard pattern to retrieve JOINed data from normalized tables?

I have the following simple "textbook" classes defined:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public int Category { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
The Category field in Product is an integer referencing the Id field in the Category class. In the database, it would be a foreign key relationship between the Product and Category tables.
But my application would need to show the friendly name of the Category of a product.
Q1: Is it correct practice to define a new class as follows:
public class ProductJ : Product
{
public string CategoryName { get; set; }
}
And then, if I now have a method getProductsJ as follows:
public class Test
{
public List<Category> Categories = new List<Category>() { ... };
public List<Product> Products = new List<Product>() { ... };
public List<ProductJ> getProductsJ()
{
var products = from p in Products
join c in Categories on p.Category equals c.Id
select new ProductJ { Id = p.Id, , Name = p.Name, CategoryName = c.Name }; //!
return products.ToList();
}
}
Q2: Is the above the best way to retrieve a list of Products with Category names?
Q3: In the select statement (//!) is there a faster way to populate the fields of the base class Product linqwithout having to enter them one by one?
Thanks.
You could project the result of the join into an object that contains a reference to both the product and category.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public int Category { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ProductCategory
{
public Product Product { get; set; }
public Category Category { get; set; }
}
class Program
{
static void Main(string[] args)
{
List<Category> Categories = new List<Category>();
List<Product> Products = new List<Product>();
var products = from p in Products
join c in Categories on p.Category equals c.Id
select new ProductCategory { Product = p, Category = c };
var list = products.ToList();
}
}
Does each book belongs to one category, or can it belong to more than one category in your case? because if a book belongs to one category then you can simply move the category name in the Book Table. also i will suggest to have a look on
MVC LINQ to SQL Table Join Record Display

Resources