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();
Related
Hey im trying to create a many to many relationship as following:
public class Book
{
public int BookId { get; set; }
public string Title { get; set; }
public Author Author { get; set; }
public ICollection<Category> Categories { get; set; }
}
public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public ICollection<Book> Books { get; set; }
}
public class Book2Category
{
public int BookId { get; set; }
public int CategoryId { get; set; }
}
The c# classes are exactly the same like the oracle database tables.
My fluent Api OnModelCreating method:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>(entity =>
{
entity.HasMany(b => b.Categories)
.WithMany(c => c.Books)
.UsingEntity<Book2Category>(d =>
{
d.HasKey(k => new { k.BookId, k.CategoryId});
});
});
modelBuilder.Entity<Category>(entity =>
{
entity.HasMany(b => b.Books)
.WithMany(c => c.Categories)
.UsingEntity<Book2Category>(d =>
{
d.HasKey(k => new { k.BookId, k.CategoryId});
});
});
}
I always get error "ORA-00904: \"BooksId\": invalid identifier" because EF Core is trying to execute the following select statement:
/*some selects before*/
left join (
select b2c.BookId, b2c.CategoryId, b2c.BooksId, b2c.CategoriesId
from Book2Category b2c
/*some more after but unimportant*/
)
So it takes the defined Keys BookId and CategoryId from OnModelCreating.
But also it genarates BooksId and CategoriesId (with an S).
This is autogenerated and comes from the properties defined in classes Book and Category.
What i want to achieve is to configure the entities in OnModelCreating() that i get rid of the two unnecessary b2c.BooksId, b2c.CategoriesId.
I know that there is a name convention for EF Core but i dont want to rename the columns in Book2Category.
Is that possible somehow?
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.
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>()
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
I have two entites in my asp.net MVC3 application and I am using EF 4.1. Entities are:
public class Category {
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Movie> Movies { get; set; }
}
public class Movie {
public int Id { get; set; }
public string Title { get; set; }
public string Director { get; set; }
public int Price {get; set;}
public DateTime ReleaseDate { get; set; }
public string Description { get; set; }
public Category Category { get; set; }
}
I want to calculate sum of prices of all movies where category name = "Comedy" using Linq query. Can you please suggest me Linq query using extension method ?
Thanks.
Assuming that you have an IEnumerable<Movie> movies, you can do
movies
.Where(x => x.Category.Name == "Comedy")
.Select(x => x.Price)
.Sum();
As #Linkgoron says in the comment, you can also put the predicate in the Sum method, such as:
movies
.Where(x => x.Category.Name == "Comedy")
.Sum(x => x.Price);