jimmy
jimmy

Reputation: 756

Entity Framework core 2.1 Many To Many Select Query

How would I create the following query using Linq?

SELECT product.name, product.code, category.Name FROM product 
INNER JOIN productCategories ON product.ID = productCategories.productID 
INNER JOIN category ON productCategories.categoryID = category.ID 
WHERE productCategories.ID = idToFind

Product & Category Classes:

public class Product
{
    public Product()
    {
        this.Categories = new HashSet<Category>();
    }    
    public int ID { get; set; }    
    public string Code { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Category> Categories { get; set; }
}


public class Category
{
    public Category()
    {
        this.Products = new HashSet<Product>();
        this.Children = new HashSet<Category>();
    }
    public int ID { get; set; }

    [StringLength(150)]
    public string Name { get; set; }
    public int? ParentID { get; set; }
    public virtual Category Parent { get; set; }

    public virtual ICollection<Category> Children { get; set; }
    public virtual ICollection<Product> Products { get; set; }
}

I have tried a few different things and can get the results if I only need columns from one table, but can not get details from both tables i.e. category name & product name.

Edit: I have now added a JunctionClass

public class CategoryProduct
{
    public int CategoryID { get; set; }
    public Category Category { get; set; }

    public int ProductID { get; set; }
    public Product Product { get; set; }

}

and tried :

var results = _context.Product.Include(e => e.categoryProducts).ThenInclude(e => e.Category).Where(c=>c.categoryProducts.Category.ID==169).ToList();

But I still cant make it work. Getting the error:

'ICollection<CategoryProduct>' does not contain a definition for 'Category' and no accessible extension method 'Category' accepting a first argument of type 'ICollection<CategoryProduct>' could be found 

Upvotes: 0

Views: 808

Answers (3)

L.Zoffoli
L.Zoffoli

Reputation: 129

Try this

var idToFind = 3;

var o = (from p in _products
         from c in p.Categories
         where c.ID == idToFind
         select new {ProductName = p.Name, ProductCode = p.Code, CategoryName = c.Name}).ToList();

Upvotes: 0

Avin Kavish
Avin Kavish

Reputation: 8947

In EF core, you need a junction table to map many-to-many relationships.

public class ProductCategory
{
    public int Id { get; set; }
    public int ProductId { get; set; }
    public Product Product { get; set; }
    public int CategoryId { get; set; }
    public Category Category { get; set; }
}

public class Product
{
    ...
    public virtual ICollection<ProductCategory> ProductCategories { get; set; }
}

public class Category
{
    ...
    public virtual ICollection<ProductCategory> ProductCategories { get; set; }
}

// DbContext
public DbSet<ProductCategory> ProductCategories { get; set; }

public override OnModelCreating(ModelBuilder builder)
{
    builder.Entity<ProductCategory>()
           .HasOne(pc => pc.Product)
           .WithMany(p => p.ProductCategories);

    builder.Entity<ProductCategory>()
           .HasOne(pc => pc.Category)
           .WithMany(c => c.ProductCategories);
}

// Query
var result = await dbContext.ProductCategories
                     .Select(pc => new {
                         ProductName = pc.Product.Name, 
                         ProductCode = pc.Product.Code, 
                         CategoryName = pc.Category.Name 
                      })
                     .SingleOrDefaultAsync(pc => pc.Id == idToFind)

Upvotes: 1

weisingxcw
weisingxcw

Reputation: 1

//Mock SomeData
List<Product> products = new List<Product>();
List<Category> category = new List<Category>();
//Linq
var result = products.SelectMany(product => product.Categories.SelectMany(productCategory => category.Where(category => category.ID == productCategory.ID).Select(category => new { category.Name, ProductName = product.Name, product.Code })));

Upvotes: 0

Related Questions