I have two classes Order and OrderDetail:
public class Order : Entity
{
public Order(KitchenAppContext context) : base(context)
{
}
public Order() : base()
{
}
public DateTime Date { get; set; }
public Guid MenuId { get; set; }
public virtual Menu Menu { get; set; }
public bool IsClosed { get; set; }
public decimal Price { get; set; }
public virtual int PeopleCount { get { return Details.Count; } }
public virtual List<OrderDetail> Details { get; set; } = new List<OrderDetail>();
}
public class OrderDetail : Entity
{
public OrderDetail(KitchenAppContext context) : base(context)
{
}
public OrderDetail() : base()
{
}
public Guid UserId { get; set; }
public virtual User User { get; set; }
public virtual List<PaymentDetail> Payments { get; set; } = new List<PaymentDetail>();
public virtual Order Order { get; set; }
public Guid OrderId { get; set; }
}
They are mapped like this:
void OrderMapping(ModelBuilder builder)
{
var etBuilder = builder.Entity<Order>();
etBuilder.HasKey(m => new { m.Id });
etBuilder.HasOne(o => o.Menu).WithMany(a => a.Orders).HasForeignKey(f => f.MenuId);
etBuilder.HasMany(o => o.Details).WithOne(d => d.Order).HasForeignKey(f => f.OrderId);
}
void OrderDetailMapping(ModelBuilder builder)
{
var etBuilder = builder.Entity<OrderDetail>();
etBuilder.HasKey(m => new { m.Id });
etBuilder.HasOne(o => o.User).WithMany(u => u.Details).HasForeignKey(f => f.UserId);
etBuilder.HasOne(o => o.Order).WithMany(u => u.Details).HasForeignKey(f => f.OrderId);
etBuilder.HasMany(o => o.Payments).WithOne(d => d.OrderDetail).HasForeignKey(f => f.OrderDetailId);
}
When I create order and order details :
var order = new Order(Context);
Context.Orders.Add(order);
var oderDetail = new OrderDetail(Context) { Order = order };
Details of order empty there and OrderId of orderdetails is null also. When I add created order detail in context then it will be added to Details and OrderId becomes Id of created order. Why it works only when I add it to context? I want that it works without adding it to context. Maybe, I should do something in consctructor of classes (with Context parameter)? How can I do this?
EDIT: Order and OrderDetails classes inherited from abstact class Entity:
public abstract class Entity
{
Guid id;
public Guid Id
{
get
{
if (id == null || id == Guid.Empty)
{
id = Guid.NewGuid();
}
return id;
}
set
{
id = value;
}
}
public Entity(KitchenAppContext context)
{
Context = context;
}
public Entity()
{
}
public MainContext Context;
}
Also, as you see, I have constructor without parameter. I created them because EF shows this message when I'm getting entities from context:
System.InvalidOperationException: 'A parameterless constructor was not found on entity type 'Order'. In order to create an instance of 'Order' EF requires that a parameterless constructor be declared.'
How can I avoid this error without creating conscrtuctors without parameter?
I solved second issue
A parameterless constructor was not found...
like this:
DbContext
property of entities will be null, because EF uses default constructor. That's why I created my own IQueryable
collection. It sets context property when it's not set:Code:
class IContextable<T> : IQueryable<T> where T : Entity
{
public IQueryable<T> SourceQuery { get; set; }
public KitchenAppContext Context { get; set; }
public IContextable(IQueryable<T> query, KitchenAppContext context)
{
SourceQuery = query;
Context = context;
}
public Type ElementType => SourceQuery.ElementType;
public Expression Expression => SourceQuery.Expression;
public IQueryProvider Provider => SourceQuery.Provider;
public IEnumerator<T> GetEnumerator()
{
foreach (var entity in SourceQuery)
{
if (entity.Context == null || entity.Context != Context)
entity.Context = Context;
yield return entity;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
And my GetEntities
method in my Context
class:
public IQueryable<T> GetEntities<T>() where T : Entity
{
IQueryable<T> query = Set<T>();
return new IContextable<T>(query, this);
}
Maybe, there was better ways, but I couldn't found them. It works now, but I'm still waiting for good answer