开发者

adding new object with exisiting children results in duplication

开发者 https://www.devze.com 2023-03-01 13:05 出处:网络
I am using entity framework 4, WCF and Silverlight. I have a many to many relationship of Order to Products.

I am using entity framework 4, WCF and Silverlight.

I have a many to many relationship of Order to Products.

 [Order]*--*[Product]
开发者_如何转开发

Using Model first, Entity Framework automatically creates the join table for me. When I create everything on the server side, things work ok. The problem comes when using Silverlight.

I bring back the list of products and display them on the screen. The user creates a new Order, and selects the Products that should be apart of the order. Then it is submitted to WCF.

var order = new order();
order.CustomerName = customerTextBox.Text;
...
order.Products = new ObservableCollection<Product>();

foreach (var product in selectedProducts)
{
   order.Products.Add(product);
}
var proxy = new OrderService();
proxy.CreateOrderAsync(order);

On the server side, it is just a very simple add method

var db = new Model1Container();
db.Products.AddObject(order);
db.SaveChanges();

However something strange happens. When this is saved, almost everything in the database gets duplicated a few times. My guess would be because Entity Framework is traversing the cyclic links a few times.

I tried changing it to db.Categories.Attatch(order). But this resulted in nothing being saved. I also tried looping and manually attaching each of the products before saving the order. But this results in an exception being thrown, stating that objects have already been attached to the context.


Edit: Doing this stops Products being duplicated. But all the Orders in the table are still duplicated. Must be traversing all the relationships still?

db.Orders.AddObject(order);
db.ObjectStateManager.ChangeObjectState(order, EntityState.Added);

foreach (var product in order.Products)
{
    db.ObjectStateManager.ChangeObjectState(product, EntityState.Unchanged);
}

db.SaveChanges();


Try this instead:

var db = new Model1Container();
db.Categories.Attach(order);
db.ObjectStateManager.ChangeObjectState(order, EntityState.Added);
db.SaveChanges();

The problem is that AddObject inserts every untracked entity in object graph. When using EF you must explicitly say EF what has changed. You will still have problems if you let users modify their orders.


Are you using WCF RIA? If not, you should consider it. The DomainServices take a way a lot of the pain.

Also, why don't you create a table 'order_position'? Like this you don't have a many to many relationship anymore. One order_position has only one order and only one product. You can also assign a price to it, which makes it save for use in statistics (what happens when you want to see how much money you made of product A, but you changed its price in the database a few times?).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号