Insert entity with one related entity which existed in the database

c# entity-framework-core

Question

I am stuck at the operation when using Entity Framework Core 2 to perform an insert of a new entity with one related entity which already existed in the database. For example, I have two objects with one to many relationship:

public Class OrderDetail
{
   public int ParentID {get;set;}
   public string OrderDetailName {get;set;}
   public int ProductID {get;set;}
   public virtual Product ProductFK {get;set;}
}

public Class Product
{
   public int ProductID {get;set;}
   public string ProductName {get;set;}
   public virtual Collection<OrderDetail> OrderDetails {get;set;} = new Collection<OrderDetail>();
}

I would like to add a new OrderDetail with an existing Product (with productID = 3) into the database, so I perform like:

private void AddOrderDetail(int productID)
{
    OrderDetail newOrderDetail = new OrderDetail();
    newOrderDetail.Name = "New OrderDetail";

    // Here I have no clue what would be the correct way...Should I do 
    // Approach A(pick related entity from database then assign as related entity to base entity):
    var ProductFromDB = DbContext.Products.SingleOrDefault(p => p.ProductID == productID);
    newOrderDetail.ProductFK = ProductFromDB;

    // Approach B(directly assign the foreign key value to base entity)
    newOrderDetail.ProductID = productID

    DbContext.SaveChange();
} 

By using approach (A), my newOrderDetail failed to save and I looked into SQL resource, looks like it considered the one that I retrieved from the database (ProductFromDB) as a new object and was trying to insert it again. I feel it's redundant job for picking ProductFromDB first then assign to the inserted entity...

By using approach (B), my newOrderDetail still failed to save, and I am getting an exception like "insert A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.", however, this exception does not happen constantly. I looked into the SQL and found the SQL Script, by running it individually in SQL Server it worked, however when running an application side, it's not working...

So what would be the correct way to deal with above scenario?

1
2
7/2/2018 12:37:44 AM

Accepted Answer

If you don't need access to the complete Product object right away, you could try to set just the foreign key column value of your newOrderDetail. Also, you need to ADD your newly created OrderDetail object to the DbContext before saving - something like this:

private void AddOrderDetail(int productID)
{
    OrderDetail newOrderDetail = new OrderDetail();
    newOrderDetail.Name = "New OrderDetail";
    newOrderDetail.ProductID = productID

    // OF COURSE, you need to ADD the newly created object to the context!
    DbContext.OrderDetails.Add(newOrderDetail);

    DbContext.SaveChange();
} 

Next time around, when you actually fetch the OrderDetail, it will resolve the linked product and you should be fine.:

using (var DbContext = new YourDbContext())
{
    OrderDetail od = DbContext.OrderDetails.FirstOrDefault(x => x.Name = "New OrderDetail");
    ....
}
2
6/30/2018 8:11:51 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow