Click here to Skip to main content
15,889,502 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi all,
I'm having a huge problem deleting records from a database using Entity Framework 4.0...
Let's say I have an Order Object with OrderDetail Objects.

Let's say my Order looks as follows:
C#
public partial class Order
{
    public bool RemoveProductFromOrder(int productId)
    {
        IEnumerable<OrderDetail> details = this.OrderDetails.Where(d => d.ProductId == productId)
        details.ToList().ForEach(d => this.OrderDetails.Remove(d));
        return details.Any();
    }
}
Pretty straightforward I'd say.
So what is the problem? Whenever I remove an OrderDetail this way the only thing that happens is that the reference of the OrderDetail to the Order is set to null. So what happens when I call ObjectContext.SaveChanges()[^]? I get an Exception saying that OrderDetail.OrderId is non-nullable and should have a value.

What is the solution to this? Pretty 'easy'...
I should hook up an event handler to the AssociationChanged Event[^] of Order.OrderDetails and remove the OrderDetail from the ObjectContext[^] manually, like so:
C#
this.OrderDetails.CollectionChanged += (sender, e) =>
{
    if (e.Action == CollectionChangeAction.Remove)
    {
        context.DeleteObject(e.Element);
    }
};
Now the problem is that I don't have a reference to my ObjectContext in every Entity[^]. I could pass a reference to every Entity, but that is not very elegant. It is also disaster waiting to happen since almost every business object would have access to data stuff.
I could hook up the event handler in the same Class where I keep my ObjectContext reference, but that would mean I have to loop through all Orders I fetch from the database(or use the ObjectMaterialized Event[^]) and hook up the event. Plus there is no way to know when a new Order was created (of course I could know, but polling every possible way for object creation and hooking up the event is also a disaster waiting to happen).

Last, I could handle the ObjectContext.SavingChanges Event[^] and check the ObjectStateManager[^] for OrderDetails that do not have an OrderId... But this is also a very nasty solution!

Is there a clean, elegant and maintainable solution to this problem? I couldn't find it and I'm about to pull my hair out (and I've got a lot!) over this problem... Any help is appreciated. Thanks!
Posted
Updated 7-Apr-12 10:28am
v2

1 solution

Your data context should be available across the entire solution. I always construct my Entity Framework in a standalone project that other projects can access.

Now in your code example the project that contains this code needs to have addressability to the framework project.

Since all you are getting is an order ID, then you must first get the order, attach the OrderDetails, then delete them.

For this being an Entity Framework question I do not find your code straightforward at all considering you never have a context available and all code is working on some local, hidden variable that may or may not be attached to some context that may or may not exist at all.

If the collection you are running that query on is actually a collection of ALL details in the entire database....you're fired.
 
Share this answer
 
Comments
Nelek 14-Apr-12 8:51am    
[quote]If the collection you are running that query on is actually a collection of ALL details in the entire database....you're fired[/quote]

Or maybe he is the one hired to clean up that mess
Sander Rossel 21-Apr-12 6:10am    
Hi, thanks for your answer and sorry for my late reply (had a very busy week).
As I understand it you are saying my ObjectContext should be a shared/static variable that every class can always access? This does not seem like a good idea.
I am saying that I query some order, for example _context.Orders.Single(o => o.ID == 1234); This returns the Order object. Now, assuming my ObjectContext is not static, unless my Order has a Property ObjectContext Context that I set right afterwards my Order has no knowledge of the ObjectContext. So how then would I delete the details from the ObjectContext?

By the way, I never said I query for ALL details in the entire database. And if I did I would have a really very good reason for it :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900