1

Having two models, Site and Link, where a site has many links, how do I delete a link from inside a method of Site, which doesn't have access to the object context?

I've tried something like:

public void DeleteFirstLink() {
    var link = LinkSet.First();
    LinkSet.Remove(link);
}

but it seems that is not really deleting the link, but breaking the association. Since there's a database constraints it throws this error:

A relationship is being added or deleted from an AssociationSet 'Sites_have_Links'. With cardinality constraints, a corresponding 'Links' must also be added or deleted.

How do I actually delete the link from the database?

4 Answers 4

1

Assuming that your ObjectContext is not alive when you call the DeleteFirstLink() method, you can make it work by spinning up a context inside the method, attaching the Site entity, and then deleting the link:

public void DeleteFirstLink()
{
  using (ProjectEntities db = new ProjectEntities())
  {
    db.AttachTo("[your site EntitySet name - SiteSet?]", this);
    var link = LinkSet.First();
    db.DeleteObject(link);
    LinkSet.Remove(link);
    db.SaveChanges();
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

I'm really curious, does that work? And I don't mean it worked once, I mean it works well and won't explode on edge cases.
I don't see any reason why it wouldn't work. You need the ObjectContext to delete an entity, so you spin one up, attach the entity and then call the "DeleteObject" method. What do you mean by "edge cases", btw?
0

You can't delete anything from the database without an object context. All actions are queued in the state manager of the object context, and those are persisted to the database when you call ObjectContext.SaveChanges(). Without SaveChanges, no DB changes.

1 Comment

I'm fine with the actions being queue, I just want to be able to queue them from inside a method in an entity.
0

First of all, it would be great if you could post a bit more information about your class structures. Does the Site class have an ObjectContext object? Then as a quick solution you could pass it into the delete method and use the context.DeleteObject() method, and call SaveChanges afterwards.

However, as a long-term solution, I will still recommend using the UnitOfWork pattern and I will post the link to the article explaining it again. The implementation might be different, but in general it might solve most of your problems (similar to this one).

The beauty of this approach is that if you use it correctly, you can build a small framework, that you can later reuse in all of your EF projects.

3 Comments

No, the Site entity doesn't have an ObjectContext, why should it?
Well, how do you manage the ObjectContext then? Are the Site and Link entities, generated by EF? Do they inherit EntityObject or are you using POCO classes? Do you extend the Site by using a partial class in a separate file?
Yes, Site and Link are entities generated by EF. I suppose they inherit EntityObject, but I would have to check. I have partial classes in separate files for Site, and maybe Link (sorry, not in front of the code right now), but if not, I can make them.
0
  1. To work with entities so the modifications are reflected in the database you MUST ADD/ATTACH these entities in object context (in terms of EF5 in database context) and then use method SaveChanges to commit changes.

  2. Yes, in EF4 to remove a record from phisical SQL table (not a link) you need to use method DeleteObject of object ObjectContext and then SaveChanges, i.e.

    using(ObjectContext context = new ObjectContext)
    {
        /* Find the removed record in object/database context (this will attaches 
         * the record to object/database context)
         * It is recommened to use FirstOrDefault() instead of First() 
         * becase this method can return null if there is no record to delete
         * instead generation of exception in case of using First()
         */
        Link linkToDelete = context.Links.FirstOrDefault(); 
        if(linkToDelete != null) 
        {
            context.DeleteObject(linkToDelete);
            context.SaveChanges();
        }
    }
    
  3. Fortunately now there is EF5 that allows to remove from parent collection but only if relation is one-to-many.

    using(DatabaseContext context = new DatabaseContext)
    {
        Link linkToDelete = context.Links.FirstOrDefault(); 
        if(linkToDelete != null)
        {
            context.Links.Remove(linkToDelete);
            context.SaveChanges();
        }
    }
    
  4. In any case DO NOT forget to call SaveChanges!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.