Assume following model
class Order()
{
public int Id {get; set;}
public List<OrderItem> Items {get; set;}
}
class OrderItem()
{
public int Id {get; set;}
public string Name {get; set;}
}
So I have an order that has 10 items, now I need to build a query that returns all Orders that have the last item in their collection property Items having Name equals to specific value. How do I do that?
Related
I am working on a project which involves EF Core.
I would like to use the foreign keys from Category with one single navigation property.
Therefore, Item stores the foreign keys of Category, and the names of the Category can be shown.
This is how the relationship looks like:
Classes:
[Table("Item" , Schema = "public")]
public class Item
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ItemID {get; set;}
public string Name {get; set;}
public int CategoryID {get; set;}
//Single Navigation Property
public Category Category {get; set;}
}
[Table("Category" , Schema = "public")]
public class Category
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CategoryID {get; set;}
public string Name {get; set;}
}
DbContext:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Item>().ToTable("Item");
modelBuilder.Entity<Category>().ToTable("Category");
modelBuilder.Entity<Item>()
.HasOne(i=>i.Category)
.WithOne()
.HasForeignKey<Item>(i=>i.CategoryID);
}
It shows an error
Duplicate key value violates unique constraint "IX_ItemDB_CategoryID"
Apparently, it means CategoryID cannot be duplicate in Item.
What am I doing wrong here? Thanks!
actually your answer in this article. What you need to do is change the location of the navigation property. So Item should not have an Category property, Category should have a collection of Item for single navigation. the article describes other ways.
In case I understand properly You need one to many relation and I can offer you that structure and if you use Migration your tables will be properly build in the database. No to do anything in the FluentApi to, Your FK, PK(identity) and Indexes will be automatically created
[Table("Item" , Schema = "public")]
public class Item
{
public int Id {get; set;}
public string Name {get; set;}
public int CategoryId {get; set;}
public Category Category {get; set;}
}
[Table("Category" , Schema = "public")]
public class Category
{
public Category()
{
this.Items = new HashSet<Item>();
}
public int Id {get; set;}
public string Name {get; set;}
public virtual ICollection<Item> Items {get; set;}
}
Ivan Stoev is correct. The model of my question is fine and fluent configurations are not required. EFCore will handle the rest.
Assuming I have a child
public class Child
{
public int Id {get; set;}
}
and two parents which using the childs in one to one relations.
One child should be used only at one parent. But I want to use the child with Id=1 at ParentA and the child with Id=2 at ParentB for example.
public class ParentA
{
public int Id {get; set;}
public int ChildId {get; set;}
public Child Child {get; set;}
}
public class ParentB
{
public int Id {get; set;}
public int ChildId {get; set;}
public Child Child {get; set;}
}
I want the navigation property at the parents if possible.
I know how to configure a one to one relation when having only one parent because then I would have to add a navigation property in the Child class and would add the configuration in the OnModelCreating method of my DbContext implementation.
But for the scenario with 2+ parents I don't know how the configuration in OnModelCreating should look like.
Based on the additional info from the comments that the ParentA and ParentB are not mapped to the same table you could implement 2 one-to-one relationships resulting in:
public class Child
{
public int Id {get; set;}
public ParentA A {get; set;}
public ParentB B {get; set;}
}
This would mean that when A is initialized B is null and vice versa.
Alternatively if ParentA and ParentB are similar enough and it makes sence to have a common inheritance:
public class Child
{
public int Id {get; set;}
public Parent {get; set;}
}
public class Parent
{
public int Id {get; set;}
public int ChildId {get; set;}
public Child Child {get; set;}
}
public class ParentA : Parent { }
public class ParentB : Parent { }
And have the one-to-one relationship mapped between Parent and Child
This might also require DB changes.
I store my data with this data structure in Elasticsearch:
class Parent {
public guid Id {get; set;}
public string Name {get; set;}
public string Description {get; set;}
public List<Child> Children {get; set;}
}
class Child
{
public float Score{get; set;}
public int QTY {get; set;}
public string Name {get; set;}
}
Now I want to find the parents who have a child with a Score more than 6 and QTY more than 4. How can I provide the property Path of this fields in my query. I didn't store children as nestet object in the parent.
I have the following models:
public class Order
{
public int Id {get; set;}
public int CustomerId {get; set;}
public virtual Category Category {get; set;}
//Many more properties...
}
public class OrderLine
{
public int Id {get; set;}
public int OrderId {get; set;}
public virtual Order Order {get; set;}
public virtual Product Product {get; set;}
//Other properties...
}
I need to get the orders of a particular customer. In order not to retrieve too many information, I created a class:
public class CustomerOrder
{
public int CustomerId {get; set;}
public int OrderId {get; set;}
public string ProductName {get; set;}
public virtual ICollection<OrderLine> {get; set;}
}
I have mapping configuration for the Order and OrderLine classes but none for CustomerOrder as I was thinking that I can project data into this class.
I can:
Use EF to retrieve the data by specifying includes. After the data is retrieved I can project it into the CustomerOrder class. However, will this force EF to retrieve all columns for the main and included tables?
Use a custom SQL query to retrieve the required details from the Order table (maybe directly from a view). The use Linq to join this resultset with OrderLine to have the complete projection. However, will I need to have mapping configuration for the view?
To avoid too many columns and join in the SQL select statement, what is the best way to project the data into CustomerOrder?
You can do it as shown below.You have to do some changes on your models as well.I have done that.Please see that too.
public class Order
{
public int Id {get; set;}
public int CustomerId {get; set;}
public virtual Category Category {get; set;}
public virtual ICollection <OrderLine> OrderLines {get; set;}
//Many more properties...
}
public class OrderLine
{
public int Id {get; set;}
public int OrderId {get; set;}
public virtual Order Order {get; set;}
public virtual Product Product {get; set;}
//Other properties...
}
public class CustomerOrder
{
public int CustomerId {get; set;}
public int OrderId {get; set;}
public string ProductName {get; set;}
public virtual ICollection<OrderLine> OrderLines {get; set;}
}
Final Query :
var orderList = (from order in _context.Orders
from orderLine in order.OrderLines)
select new CustomerOrder
{
CustomerId = order.CustomerId,
OrderId = orderLine.OrderId,
ProductName= orderLine.Product.ProductName,
OrderLines = order.OrderLines
}).AsNoTracking().ToList();
A 1 : No.Only the projected columns will be fetched from the db.
Best Approach : Always use the custom projection (like CustomerOrder).That is the best when we consider the Performance of the EF query.You can use that to send data to the View too (it's like a DTO (Data Transfer Object)).
I would like to implement an Editor in ASP.NET MVC application for a Model with ICollection property in it.
public class Peson
{
public int Id {get; set;}
public int Name {get; set;}
public ICollection<PersonCode> {get; set;}
}
public class PersonCode
{
public int PersonId {get; set;}
public int Code {get; set;}
public int SubCode {get; set;}
}
In PersonCode class each SubCode depends on Code for example for Code 1 we can choose only SubCodes 2,3 and for Code 2 SubCodes 5,7
Each Code and SubCode has a description stored somewhere in database
So I need to edit this collection (add,delete,edit items in it) inside my Person object on a single Person Edit page and also provide dropdown lists for choosing Code and SubCode.