H Mihail
H Mihail

Reputation: 623

Strange behavior in Entity Framework with a list

I have an winforms order taking app for a restaurant. On startup I read the list of products available as this:

var products = context.Products.AsNoTracking().OrderBy(p => p.Id).ToList();

When the user clicks the button corresponding to a menu Item, I identify the product to be added to the order like this:

var product = products.FirstOrDefault(p => p.Id == menuItem.ProductId);
var orderItem = new OrderItem
{
    ProductId = product.Id,
    Quantity = 1,
    UnitPrice = product.Price,
    ListValue = 1 * product.Price,
    Product = product
};

Here is the OrderItem entity:

public partial class OrderItem
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public int OrderId { get; set; }
    public int ProductId { get; set; }
    public decimal Quantity { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal TotalValue { get; set; }

    public Order Order { get; set; }
    public Product Product { get; set; }
}

After saving the order, some strange things happen (for me anyway): The product in the list changes its Id, as if it is a new product, with the same attributes. Also after context.SaveChanges() in the database I will have 2 rows of the same product.

Anyone can point out what I am doing wrong?

Upvotes: 0

Views: 77

Answers (3)

Philip Stuyck
Philip Stuyck

Reputation: 7447

You have obtained the list of products as NoTracking. But then you assign it to the product in the orderitem, effectively pulling the object back in. If you just leave out that statement and do this instead

var product = products.FirstOrDefault(p => p.Id == menuItem.ProductId);
var orderItem = new OrderItem
{
    ProductId = product.Id,
    Quantity = 1,
    UnitPrice = product.Price,
    ListValue = 1 * product.Price,
    //Product = product don't do this
};

then it will work ok.

Upvotes: 1

H Mihail
H Mihail

Reputation: 623

After reading the question @Jehof mentioned, I solved it by reattaching the products to the new context in which SaveChanges() occurs:

products.ForEach(p => context.Products.Attach(p));
context.SaveChanges();

Thanks for your comments!

Upvotes: 0

Gert Arnold
Gert Arnold

Reputation: 109080

When you Add the Order, the Product is also changed to Added. You can simply prevent this by removing the assignment

Product = product

It is enough to set ProductId.

Upvotes: 1

Related Questions