I have the following entity tree:
ParameterDefinition-->ParameterOperation
ParameterDefinition-->ParameterGroup-->Parameter
Also there is a many to many relationship (mapped to a FK-FK table) between ParameterOperation and Parameter.
All associations are declared as Delete cascade (only the many to many is not Delete cascade).
The thing is that when I MarkAsDeleted Parameter Object through ParameterOperation
(ParameterDefinition.ParameterOperations[0].Parameters[0].MarkAsDeleted) it is deleted from DB and the map table is updated as well (row is deleted), but when I try to delete Parameter From ParameterGroup
(ParameterDefinition.ParameterGroups[0].Parameters[0].MarkAsDeleted) it is not deleted at all (no delete query is executed on DB).
What might be the problem?
Also how do i delete a many to many relationship? for example I want to keep all Parameters and all ParameterOperations but I want to delete the relationship between Parameters[0] and ParameterOperations[0].
How can I do it?
if I set the NavigationProperty - ParameterDefinition.ParameterOperations[0].Parameters.MarkAsDeleted it actually deleted the Parameter from DB what I don't want
Simply removing the Parameter Entity from the ParameterOperation's collection, and then saving your context should be enough to delete the many to many relationship that exists in the junction table.
ParameterDefinition.ParameterOperations[0].Parameters.Remove(ParameterDefinition.ParameterOperations[0].Parameters[0]);
Context.SaveChanges();
Related
Problem: When adding an object "Order" to my dbcontext, all nested objects of the order gets "readded" to the database, though the nested objects is static data and only a reference shoudl be added in the database.
Example:
The database holds 0 orders, and 3 items.
I add one order with 2 items.
Now the database hold 1 order, and 5 items. The two items in the order has been "readded" to the database, even though the items had the right primary keys before db.SaveChanges().
I realize that i may be able to attach the existing items to the dbcontext before saving changes, but is that really the only way to go? Can't EF figure out that to item already exists when the primary key matches an existing item?
Does anyone know if this is different in the new version of EF CodeFirst?
No EF cannot figure if entities are existing one or new one - both Add and Attach commands are graph oriented operations. You call them on one entity in the graph and they traverse all relations (and their relations and so on) and perform the operation for them as well.
You must figure correct state of each entity in the graph for example by using:
dbContext.Orders.Add(newOrder);
foreach(var item in newOrder.Items) {
dbContext.Entry(item).State = EntityState.Unchanged;
}
dbContext.SaveChanges();
You can use the reverse operation by calling Attach(newOrder) and set the order to Added state. The main difference will come with independent associations (for example many-to-many relations). The first approach will correctly add new relation between order and each item whereas second will not unless you manually set each relation to Added state (and changing state for relations is more complex).
I have a simple and beginner question.
I have two tables with 1 to N relationship. I want to when I delete a row in parent table, in an
other table the child of that row delete too.
How can I do that using entity framework?
Probably it was asked before, refer to the link below:
Delete an object and all of its related entities in Entity Framework
I do believe that you should handle that at Database level by using CASCADE DELETE ON.
I have 3 normalised tables consisting of Employees, Departments and EmployeesToDepartments. I wish to be able to assign an Employee to one or more Department, hence the link table (EmployeesToDepartments). I can successfully query the database and extract the full hierarchy of entities via the Navigation properties using
this.ObjectContext.Employees.Include("EmployeesToDepartments").Include("EmployeesToDepartments.Department")
plus the [Include] attribute in the metadata, thus allowing me to access the Departments for a given Employee. Upon trying to remove a link between an [Employee] and [Department] in the [EmployeesToDepartments] table I was given a Foreign Key Constrain error.
I have simplified my model to include just one navigation property between [Employees] and [EmployeesToDepartments]. A Foreign Key constraint between[Employees].[ID] and [EmployeesToDepartments].[IDEmployee] was preventing me from updating the EmployeesToDepartments table. With this removed via a Relationship setting I can now update the table. I can now execute the following code
foreach (var rel in _employee.EmployeesToDepartments)
{
_employee.EmployeesToDepartments.Remove(rel);
}
_domainContext.SubmitChanges();
without error.
I was expecting to see the entries in the RelEmployeesToDepartments with the IDEmployee to have been deleted. What I see in the table are the value 0 where the IDEmployee previously was.
Is it possible to force a DELETE statement to be issued? Am I misunderstanding the basic concepts here?
Any help would be much appreciated.
Removing entities in navigation property only breaks the link between entities. You have to delete from the EntitySet to achive what you want.
ex)
myDomainContext.EmployeeDepartments.Remove(employeeDepartmentToRemove);
myDomainContext.SubmitChanges();
I have two tables in an existing (MSSQL 2008 R2) database that are related by a link table.
The two tables are "Plan" and "Tips". The link table is "PlanTipLinks".
Plans can have many tips, and tips can be associated with multiple plans (i.e. it's a many-to-many relationship). In the application, I only care about the "Plan.Tips" relationship. I don't need the Tip.Plans inverse relationship.
The foreign key references in the link table cannot be null.
I'm using the following fluent API code to map this relationship:
modelBuilder.Entity<Plan>()
.HasMany(p => p.Tips)
.WithMany()
.Map("PlanTipLinks", (p, t) =>
new
{
PlanId = p.Id,
TipId = t.Id
});
This create the correct entries in the table. Problem is that, when I delete a plan, I get a foreign key exception on the PlanTipLinks table.
Presumably I need to tell it to cascade into the PlanTipLinks table when a plan is deleted, but I'm not sure how to do that. I don't seem to be able to call the WillCascadeOnDelete method using the HasMany/WithMany methods.
What am I missing here?
As of EF CTP4, there is no way to directly turn on cascade deletes on Many to Many associations by Fluent API.
That said, if your intention is to make sure that you can delete the principle (e.g. a Plan record) without having to worry about the dependent record in the link table (i.e. PlanTipLinks) then you don't need to turn on cascades on the database since EF Code First will take care of the cascade deletes on the client side when it comes to Many to Many associations.
For example, when you delete a Plan object, code first is smart enough to first send a delete statement to get rid of the dependent record in the PlanTipLinks table and after that it will send another delete statement to delete the Plan record.
For more info, please take a look at the following post:
EF CTP4 cascade delete on many to many relationship
What is the best way to delete an object (and its child objects) using EF? I'd like to pass just the id for the object to delete, and have EF handle deleting its dependent data (foreign key'd data). Do I have to retrieve the object first based on the id and then call "DeleteObject"?
If you have cascade configured in the database, then deleting the principle should be enough.
You can do this without a query to the database to GET the thing to be deleted using Stub entities like this:
var stub = new Principal{ID = idToDelete};
ctx.AttachTo("PrincipalsEntitySetName", stub);
ctx.DeleteObject(stub);
Of course this is not the whole story if there are references or fields used for concurrency checks you will need those too.
If on the other hand you only have a cascade delete in the model (i.e. there is no cascade in the database) you will need to get ALL the dependents in memory first, and then call delete:
var stub = new Principal{ID = idToDelete};
ctx.AttachTo("PrincipalsEntitySetName", stub);
stub.Dependendents.Load();
ctx.DeleteObject(stub);
This only works because the EF issues (what it expects to be ) redundant deletes to keep the ObjectContext in sync with what it expects to happen in the database.
Hope this helps
Alex
PS I have some tips on this topic on my MSDN blog. Check out tip 33 (cascade delete) and tip 26 (stub entities)