i have problem
i have A CategoryEntity Class :
public class Category : IId
{
[Key] public int Id { get; set; }
[Required] public string Name { get; set; }
public List<SubToCat> SubToCat { get; set; }
}
and SubCategory Entity Class :
public class SubCategory : IId
{
[Key] public int Id { get; set; }
[Required] public string Name { get; set; }
public List<SubToCat> SubToCat { get; set; }
}
and its my SubToCat entity class :
public class SubToCat
{
public int SubCategoryId { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
public SubCategory SubCategory { get; set; }
}
now in Get method for all SubCategory i want to join the all of categories where its CategoryId is same as CategoryId
but i dont know how, Can you plz Help me
I'm assuming you are using some Entity Framework :
_dbContext.SubCategories.Where(s => s.SubToCat.Category == CategoryId)
You do not need join. Just use SelectMany as code below :
class Program
{
static void Main(string[] args)
{
DataContext db = new DataContext();
var results = db.Category.SelectMany(x => x.SubToCat.SelectMany(y => y.SubCategory.SubToCat.Select(z => new {
catId = x.Id,
catName = x.Name,
subToSubCatId = y.SubCategoryId,
subToCatId = y.CategoryId,
subToCategory = y.Category,
subToCatSubCatId = z.SubCategory.Id,
subToCatSubCatName = z.SubCategory.Name
}).ToList():
}
}
public class DataContext
{
public List<Category> Category { get; set; }
}
public class IId
{
}
public class Category : IId
{
public int Id { get; set; }
public string Name { get; set; }
public List<SubToCat> SubToCat { get; set; }
}
public class SubCategory : IId
{
public int Id { get; set; }
public string Name { get; set; }
public List<SubToCat> SubToCat { get; set; }
}
public class SubToCat
{
public int SubCategoryId { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
public SubCategory SubCategory { get; set; }
}
Try
_dbContext.SubCategories
.Include(x => x.SubToCat)
.Include(x => x.Category)
This will bring in all Sub Categories as well the joining table and relevant Categories in a single SQL Query using 2 joins.
Related
I'm creating a KPI dashboard that displays the total income from orders. The business logic is that each item is linked to a type of event with a many to many relationship , and linked to a supplier type via a one to many relationship. And there are different suppliers which sell these items based on the supplier type. There is also a table that links suppliers to their order by using the orderItemId and supplierId. What I'm trying to achieve is the following:
Get all orders that have been successfully fulfilled and get their order items.
Get the supplier order items from the table I mentioned above using the order items.
Once I have the supplier order items, I want to group them by the supplierId, and iem event type id so that I can display the items that each supplier sold of each event type.
Supplier
Event Type
List of items
Supplier
Event Type
List of items
The above is what I want to happen. I managed to group them by supplier id but I'm struggling to group them by eventTypeId because of the many to many relationship between the item and the event types.
Here are the models:
public partial class Item
{
public Item()
{
Favorites = new HashSet<Favorite>();
ItemDetails = new HashSet<ItemDetail>();
ItemEventTypes = new HashSet<ItemEventType>();
OrderItems = new HashSet<OrderItem>();
SupplierItems = new HashSet<SupplierItem>();
}
[Key]
public int Id { get; set; }
[StringLength(250)]
public string Image { get; set; }
public string Description { get; set; }
[StringLength(200)]
public string Title { get; set; }
public int? CategoryId { get; set; }
[Column("isDeleted")]
public bool? IsDeleted { get; set; }
public double? Price { get; set; }
public int? EventTypeId { get; set; }
public int? NumberOfGuestsId { get; set; }
public double? DaberniPrice { get; set; }
public double? RegularPrice { get; set; }
public int? Tax { get; set; }
[Column("SupplierTypeID")]
public int? SupplierTypeId { get; set; }
[Column("SortID")]
public int? SortId { get; set; }
public bool? IsDisabled { get; set; }
public int? Min { get; set; }
public int? Max { get; set; }
public int? Increment { get; set; }
public bool? IsShisha { get; set; }
public bool? IsSoldByPackage { get; set; }
[Column("ImageAR")]
[StringLength(250)]
public string ImageAr { get; set; }
[Column("DescriptionAR")]
public string DescriptionAr { get; set; }
[Column("TitleAR")]
[StringLength(250)]
public string TitleAr { get; set; }
public int? Capacity { get; set; }
[ForeignKey(nameof(CategoryId))]
[InverseProperty(nameof(Catrgory.Items))]
public virtual Catrgory Category { get; set; }
[ForeignKey(nameof(NumberOfGuestsId))]
[InverseProperty(nameof(NumberOfGuest.Items))]
public virtual NumberOfGuest NumberOfGuests { get; set; }
[ForeignKey(nameof(SupplierTypeId))]
[InverseProperty("Items")]
public virtual SupplierType SupplierType { get; set; }
[InverseProperty(nameof(Favorite.Item))]
public virtual ICollection<Favorite> Favorites { get; set; }
[InverseProperty(nameof(ItemDetail.Item))]
public virtual ICollection<ItemDetail> ItemDetails { get; set; }
[InverseProperty(nameof(ItemEventType.Item))]
public virtual ICollection<ItemEventType> ItemEventTypes { get; set; }
[InverseProperty(nameof(OrderItem.Item))]
public virtual ICollection<OrderItem> OrderItems { get; set; }
[InverseProperty(nameof(SupplierItem.Item))]
public virtual ICollection<SupplierItem> SupplierItems { get; set; }
}
public partial class ItemEventType
{
[Key]
public int Id { get; set; }
public int? EventTypeId { get; set; }
public int? ItemId { get; set; }
public bool? IsDeleted { get; set; }
[ForeignKey(nameof(EventTypeId))]
[InverseProperty("ItemEventTypes")]
public virtual EventType EventType { get; set; }
[ForeignKey(nameof(ItemId))]
[InverseProperty("ItemEventTypes")]
public virtual Item Item { get; set; }
}
public partial class SupplierAssignedOrderItem
{
[Key]
public int Id { get; set; }
[Column("SupplierID")]
public int? SupplierId { get; set; }
[Column("ItemID")]
public int? ItemId { get; set; }
public int? Status { get; set; }
[Column(TypeName = "datetime")]
public DateTime? CreatedDate { get; set; }
[ForeignKey(nameof(ItemId))]
[InverseProperty(nameof(OrderItem.SupplierAssignedOrderItems))]
public virtual OrderItem Item { get; set; }
[ForeignKey(nameof(Status))]
[InverseProperty(nameof(OrderStatus.SupplierAssignedOrderItems))]
public virtual OrderStatus StatusNavigation { get; set; }
[ForeignKey(nameof(SupplierId))]
[InverseProperty("SupplierAssignedOrderItems")]
public virtual Supplier Supplier { get; set; }
}
Any Help is appreciated. Thanks.
I tried with EF Core,you could get orders and Supplier as follow :
DBcontext:
public class EFCoreDbContext : DbContext
{
public EFCoreDbContext(DbContextOptions<EFCoreDbContext> options)
: base(options)
{
}
public DbSet<Item> Item { get; set; }
public DbSet<Order> Order { get; set; }
public DbSet<Supplier> Supplier { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Item>().ToTable("Item");
modelBuilder.Entity<Order>().ToTable("Order");
modelBuilder.Entity<OrderItem>().HasKey(x => new { x.ItemId, x.OrderId });
modelBuilder.Entity<OrderItem>().HasOne(x => x.Item).WithMany(x => x.OrderItems).HasForeignKey(x => x.ItemId);
modelBuilder.Entity<OrderItem>().HasOne(x => x.Order).WithMany(x => x.OrderItems).HasForeignKey(x => x.OrderId);
modelBuilder.Entity<OrderItem>().ToTable("OrderItem");
modelBuilder.Entity<Supplier>().HasMany(x => x.Orders).WithOne(x => x.Supplier).HasForeignKey(x => x.SupplierId);
modelBuilder.Entity<Supplier>().ToTable("Supplier");
modelBuilder.Entity<SupplierItem>().HasKey(x => new { x.ItemId, x.SupplierId });
modelBuilder.Entity<SupplierItem>().HasOne(x => x.Item).WithMany(x => x.SupplierItems).HasForeignKey(x => x.ItemId);
modelBuilder.Entity<SupplierItem>().HasOne(x => x.Supplier).WithMany(x => x.SupplierItems).HasForeignKey(x => x.SupplierId);
modelBuilder.Entity<SupplierItem>().ToTable("SupplierItem");
}
controller:
var orderlist = _context.Order.Include(p => p.OrderItems).ThenInclude(q => q.Item).ToList();
var supplierlist = _context.Supplier.Include(p => p.SupplierItems).ThenInclude(q => q.Item).ToList();
And I think it'll be better if you remove some properties from your itemclass and add them to SupplierItem class,such as the price property and Event Type property.
an item may have different prices if you buy from different supplies,also in different days. If the event type is used to describe the state of the trade ,it should be removed as well.
public class Item
{
public Item()
{
OrderItems = new List<OrderItem>();
SupplierItems = new List<SupplierItem>();
}
public int ItemId { get; set; }
public string ItemName { get; set; }
public List<OrderItem> OrderItems { get; set; }
public List<SupplierItem> SupplierItems { get; set; }
}
public class Supplier
{
public Supplier()
{
Orders = new List<Order>();
SupplierItems = new List<SupplierItem>();
}
public int SupplierId { get; set; }
public string SupplierName { get; set; }
public List<Order> Orders { get; set; }
public List<SupplierItem> SupplierItems { get; set; }
}
public class SupplierItem
{
public Item Item { get; set; }
public int ItemId { get; set; }
public Supplier Supplier { get; set; }
public int SupplierId { get; set; }
public double SupplierItemPrice { get; set; }
}
If you really want to group the supplier list by two properties
you could try:
var somesupplierslist = supplierlist.GroupBy(x => new { x.SupplierId, x.SupplierName }).ToList();
I am working on a Asp.net core 2.2 project and have a problem about loading related data in ViewModel.
First of all i have a table named QuestionTbl :
public class Question
{
[Key]
public int questionID { get; set; }
public string questionTitle { get; set; }
public string GroupID { get; set; }
}
As you see i have a string property called GroupID in Question table that shows groups of each question.
For Example
1 row in questionTbl
---------
questionID = 1
questionTitle = 'What is Your Name ?'
GroupID = '3,4,5'
In the example above question with ID = 1 is in 3 groups (3 and 4 and 5).
And GroupTbl :
public class Group
{
[Key]
public int GroupID { get; set; }
public string GroupName { get; set; }
}
Now i want to show list of question with related groups.
I have a ViewModel like this :
public class GetQuestionViewModel
{
public int questionID { get; set; }
public string questionTitle { get; set; }
public ICollection<Group> QuestionGroups { get; set; }
}
And my entity framework query :
var questionQuery = (from a in _db.QuestionTbl
select new GetQuestionViewModel()
{
questionID = a.questionID,
questionTitle = a.questionTitle
})
.Include(q => q.QuestionGroups)
.ToList();
I want to have a list contains questions and groups of each question. But QuestionGroups returns null in my query. I also read this link but it did not help me.
You could not use Include here for a viewModel directly.I advice that you could use many-to-many relationship for your Question and Group models.
Models:
public class Question
{
[Key]
public int questionID { get; set; }
public string questionTitle { get; set; }
public List<QuestionGroup> QuestionGroups { get; set; }
//public List<Group> Groups { get; set; }
//public string GroupID { get; set; }
}
public class Group
{
[Key]
public int GroupID { get; set; }
public string GroupName { get; set; }
public List<QuestionGroup> QuestionGroups { get; set; }
}
public class QuestionGroup
{
public int QuestionId { get; set; }
public Question Question { get; set; }
public int GroupId { get; set; }
public Group Group { get; set; }
}
public class GetQuestionViewModel
{
public int questionID { get; set; }
public string questionTitle { get; set; }
public ICollection<Group> QuestionGroups { get; set; }
}
DbContext;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<QuestionGroup>()
.HasKey(t => new { t.QuestionId, t.GroupId });
modelBuilder.Entity<QuestionGroup>()
.HasOne(qg => qg.Question)
.WithMany(q => q.QuestionGroups)
.HasForeignKey(qg => qg.QuestionId);
modelBuilder.Entity<QuestionGroup>()
.HasOne(qg=>qg.Group)
.WithMany(g => g.QuestionGroups)
.HasForeignKey(qg => qg.GroupId);
}
EF Core query;
var questionQuery = (from a in _context.QuestionTbl.Include(q => q.QuestionGroups)
select new GetQuestionViewModel()
{
questionID = a.questionID,
questionTitle = a.questionTitle,
QuestionGroups = a.QuestionGroups.Select(qg => qg.Group).ToList()
})
.ToList();
Normalize your tables, following the Microsoft Docs:
Question:
public class Question
{
[Key]
public int questionID { get; set; }
public string questionTitle { get; set; }
public int GroupID { get; set; }
[ForeignKey("Group_ID")]
public virtual Group Group { get; set; }
}
Group:
public class Group
{
[Key]
public int GroupID { get; set; }
public string GroupName { get; set; }
public virtual List<Question> questions { get; set; }
}
At this point you can query the records like so:
db.Question.Include(q => q.Group)
I can't seem to load the products from InFrontPages on grandchild levels or deeper in this query. Products are loaded for the first level of sub categories, but for all deeper levels, it just returns null:
var categories = await _context.ProductCategories
.Include(e => e.ProductInCategory)
.ThenInclude(e => e.Product)
.ThenInclude(f => f.InFrontPages)
.AsQueryable() // <-- Force full execution (loading) of the above
.Where(e => e.ParentId == id) // <-- then apply the parent id filter
// (id can be `null` (for root categories), or a category Id)
.OrderBy(o => o.SortOrder)
.ToListAsync();
The models:
public class ProductCategory
{
public int Id { get; set; }
public string Title { get; set; }
public int SortOrder { get; set; }
[ForeignKey(nameof(ParentCategory))]
public int? ParentId { get; set; }
public ProductCategory ParentCategory { get; set; } //nav.prop to parent
public ICollection<ProductCategory> Children { get; set; } = new List<ProductCategory>();
public ICollection<ProductInCategory> ProductInCategory { get; set; }
public ICollection<FrontPageProduct> FrontPageProduct { get; set; }
}
public class ProductInCategory
{
public int Id { get; set; }
public int ProductId { get; set; }
public int ProductCategoryId { get; set; }
public int SortOrder { get; set; }
public Product Product { get; set; }
public ProductCategory ProductCategory { get; set; }
}
public class Product
{
public int Id { get; set; }
public int? ProductTypeId { get; set; }
public string Title { get; set; }
public string Info { get; set; }
public string LongInfo { get; set; }
public decimal Price { get; set; }
public int? Weight { get; set; }
// A product can belong to multiple category front pages
public ICollection<FrontPageProduct> InFrontPages { get; set; }
// A product can belong to multiple categories
public ICollection<ProductInCategory> InCategories { get; set; }
}
public class FrontPageProduct
{
public int Id { get; set; }
public int ProductCategoryId { get; set; }
public int ProductId { get; set; }
public int SortOrder { get; set; }
public Product Product { get; set; }
public ProductCategory ProductCategory { get; set; }
}
What am I missing?
I have a Model:
public class Transaction
{
public Guid ID { get; set; }
public Guid CategoryID { get; set; }
public List<Guid> Tags { get; set; }
}
public class Category
{
public Guid ID { get; set; }
public string Caption { get; set; }
}
public class Tag
{
public Guid ID { get; set; }
public string Caption { get; set; }
}
I have a ModelRepository of Model objects. I have VieModels:
public class TransactionViewModel
{
public Guid ID { get; set; }
public CategoryViewModel Category { get; set; }
public List<TagViewModel> Tags { get; set; }
}
public class CategoryViewModel
{
public Guid ID { get; set; }
public string Caption { get; set; }
}
public class TagViewModel
{
public Guid ID { get; set; }
public string Caption { get; set; }
}
Now I need to make List<TransactionViewModel> from List <Transaction> using linq. How did I:
VM.Categories = ModelRepository.Categories.Select(p => new CategoryViewModel(p)));
VM.Tags = ModelRepository.Tags.Select(p => new TagViewModel(p)));
var trans = from t in ModelRepository.Transactions
join c in VM.Categories on t.CategoryID equals c.ID
select new TransactionViewModel()
{
...,
Category = c
};
VM.Transactions = trans.ToList();
Now when I change any CategoryViewModel in VM.Categories, I immediately get changes for all TransactionViewModel.Category in VM.Transactions. Question - how do I fill TransactionViewModel.Tags? Preferably with LINQ. And it's mandatory that when changing any TagViewModel in VM.Tags, I immediately get changes for all TransactionViewModel.Tags in VM.Transactions.
My question is this. Let's say I have a Category class and Product class. And they are implemented like this :
Category :
public class Category
{
public Category()
{
this.Products = new ObservableCollection<Product>();
}
public int CategoryId { get; set; }
public string Name { get; set; }
public virtual ObservableCollection<Product> Products { get; private set; }
}
And Product :
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
}
My question is this. If their id names were both "Id", how could I set the same relationship between Category and Product? In this example I can easily put CategoryId in product because the IDs have different names. What if they had the same name? What should I do? Thanks.
I think just renaming their Id(s) to "Id" work perfectly as you expected.
public class Category
{
public Category()
{
this.Products = new ObservableCollection<Product>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ObservableCollection<Product> Products { get; private set; }
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
}
Result