问题
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?
回答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();
}
}
回答2:
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.
回答3:
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.
回答4:
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.
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(); } }
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(); } }
- In any case DO NOT forget to call SaveChanges!
来源:https://stackoverflow.com/questions/2097883/how-to-delete-an-associated-object-in-entity-framework-without-having-access-to