Delete parent if no children in EF Core 7 - c#

Using EF Core 7 and .NET 7 (but also in previous versions), it is possible to delete all children of a one-to-many relationship in a SQL server database by configuring the delete behavior of the parent entity in the OnModelCreating-method in the class deriving from the DbContext-class, like this:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Department>()
.HasMany(d => d.Employees)
.WithOne(e => e.Department)
.OnDelete(DeleteBehavior.Cascade)
}
}
But what if I want to delete the parent if all child entities are deleted?
I've tried mapping a reversed delete pattern from the one above (see below), but to no success.
modelBuilder.Entity<Employee>()
.HasOne(e => e.Department)
.WithMany(d => d.Employees)
.OnDelete(DeleteBehavior.Cascade);

ORM engines are inspired from the relational database management systems. Removing a parent when last child is removed is not a standard operation on a relation change in the DB engines. So EFCore does not support it to. At the database level you can use triggers to achieve what you want.

Related

Add id column in self referencing many-to-many table in entity framework

I have a Person class which can have Relatives which is a self reference many-to-many relationship(Relative is also a Person). I wanted to maintain this Person->Relatives mapping in a separate table. So, to create this relationship in EF, I did this:
modelBuilder.Entity<Person>()
.HasMany(e => e.Relatives)
.WithMany()
.Map(c =>
{
c.MapLeftKey("PersonId");
c.MapRightKey("RelativeId");
c.ToTable("PersonRelative");
});
Now, this created a new table PersonRelative with two columns PersonId and RelativeId automatically as I planned. It also have composite primary key on PersonId and RelativeId.
Now, there're two things I wish to do here:
I want to add a new identity "Id" column in this new PersonRelative table for better performance. How can I do that?
Now, can I create a separate class for PersonRelative table, the way we have a class for every table. Because that would try creating the table again. So, I think I can either keep that fluent api mapping or the PersonRelative class. Is this correct?
I would really appreciate any help here.
you can achieve two points by the following code:
modelBuilder.Entity<PersonRelative>().HasKey(x => x.Id);
modelBuilder.Entity<PersonRelative>()
.HasOne<Person>(x => x.Person)
.WithMany(s => s.PersonRelative)
.HasForeignKey(x => x.PersonId);
modelBuilder.Entity<PersonRelative>()
.HasOne<Realtive>(x => x.Realtive)
.WithMany(s => s.PersonRelative)
.HasForeignKey(x => x.RelativeId);
it's how to make many-to-many relation in entity framework core, as it's not supported yet in core, you can use it in non-core entity framework too.
Please Note, if you want a new table mapping just for accessing data with navigation properties, then you can add property of type "ICollection" for Students in Relative Class, and the same for Student Class you can add ICollection for access Relatives from Student

Entity Framework 6 fluent api delete cascade on n:n relationship [duplicate]

I want to disable cascade deletes for a link table with entity framework code-first. For example, if many users have many roles, and I try to delete a role, I want that delete to be blocked unless there are no users currently associated with that role. I already remove the cascade delete convention in my OnModelCreating:
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
...
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
And then I set up the user-role link table:
modelBuilder.Entity<User>()
.HasMany(usr => usr.Roles)
.WithMany(role => role.Users)
.Map(m => {
m.ToTable("UsersRoles");
m.MapLeftKey("UserId");
m.MapRightKey("RoleId");
});
Yet when EF creates the database, it creates a delete cascade for the foreign key relationships, eg.
ALTER TABLE [dbo].[UsersRoles] WITH CHECK ADD CONSTRAINT [FK_dbo.UsersRoles_dbo.User_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[User] ([UserId])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[UsersRoles] WITH CHECK ADD CONSTRAINT [FK_dbo.UsersRoles_dbo.Role_RoleId] FOREIGN KEY([RoleId])
REFERENCES [dbo].[Role] ([RoleId])
ON DELETE CASCADE
GO
How can I stop EF generating this delete cascade?
I got the answer. :-) Those cascade deletes were being created because of ManyToManyCascadeDeleteConvention. You need to remove this convention to prevent it from creating cascade deletes for link tables:
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
I believe that turning off ManyToManyCascadeDeleteConvention globally is not a wise option. Instead, it's better to turn it off only for the concerned table.
This can be achieved through editing the generated migration file, for property cascadeDelete. For example:
AddForeignKey("dbo.UsersRoles", "UserId", "dbo.User", "UserId", cascadeDelete: false);
I agree with Ebram Khalil that turning it off for a single table is a good option. I like to stick as close to the automatically built migrations as I can, however, so I would set it up in OnModelCreating:
modelBuilder.Entity<User>()
.HasMany(usr => usr.Roles)
.WithMany(role => role.Users)
.Map(m => {
m.ToTable("UsersRoles");
m.MapLeftKey("UserId");
m.MapRightKey("RoleId");
})
.WillCascadeOnDelete(false);
I believe this preserves the delete going the other direction, so if both needed to be blocked (makes sense in this example) a similar call would need to be made starting with Entity<User>(Role)
Of course, this comes ages after the question was asked. So it may not have been valid in 2012.
This works for me in EFCore 6.0.1 and MySql, according to ms docs.
Note: Don't forget to regenerate your migration files after this.
// In your dbContext class
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<User>()
.HasMany(usr => usr.Roles)
.WithMany(role => role.Users)
.OnDelete(DeleteBehavior.Restrict);
}

Entity Framework 6.12 cascade Delete ( one to many relationship)

i have two table parent(id p_key,name) and child(addresid,city, id ForeignKey) table have one to many relationship ,
so if i am deleting any recording from parent table then all related record should be deleted from child table
i am using entity framework code first approach
Add this to your DB Context:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<parent>()
.HasOptional(c => c.child)
.WithOptionalDependent()
.WillCascadeOnDelete(true);
}
Have a look at this:Enabling Cascade Delete

Configure Entity Framework v6 Code-First Identifiers to use ALL CAPS

I would like Entity Framework v6 to not use quotes around identifiers when executing transactions against the database. Is it possible to configure the DbContext to do this without creating a configuration file for every entity?
For example:
Instead of
SELECT "ApplicationId"
FROM "dbo"."Applications";
I want
SELECT ApplicationId
FROM dbo.Applications;
Will Entity Framework be able to correctly map properties and entities to the database fields and tables correctly?
EDIT:
Rather than try to eliminate the quotation marks, I should have indicated that my goal is to interface with an Oracle DB. Oracle will require using quotation marks around identifiers that contain lowercase letters. So, I should probably change my request to indicate that I need all uppercase identifiers.
I came up with part of a solution in the OnModelCreating method of the DbContext, but it won't handle Foreign Key identifiers:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Properties()
.Configure(c => c.HasColumnName(c.ClrPropertyInfo.Name.ToUpperInvariant()));
modelBuilder.Types()
.Configure(c => c.ToTable(c.ClrType.Name.ToUpperInvariant()));
}
You can put the foreign key properties in your class, and then map their database column. Like this How to configure DbContext to work with Oracle ODP.Net and EF CodeFirst?
Or, if you don't want to put the foreign key property in the classes, you should use the fluent API to map the foreign key using uppercase letters. Like this example:
modelBuilder.Entity<Course>()
.HasRequired(c => c.Department)
.WithMany(t => t.Courses)
.Map(m => m.MapKey("CHANGEDDEPARTMENTID"));

EF4 CTP5 - Many To One Column Renaming

How do I override the default convention for the foreign key column in EF4 to specify a different column name?
For example, I have one entity with a property called Parent that references to other one of the same type.
EF4 tries to resolve the relation by looking for the foreign key named EntityId, but in my DB schema it is Entity_Id. How do I tell EF that the FK column name is not EntityId?
I've tried the following:
modelBuilder.Entity<SomeEntity>()
.HasOptional(m => m.Parent)
.WithMany()
.IsIndependent()
.Map(m => m.MapKey(k => k.Id, "Entity_Id")));
But I get an exception saying: Sequence contains more than one matching element.
Any help on this?
Thanks!
First: Upgrade to EF 4.1 RTW. CTP 5 is outdated and contains potentially many bugs which are fixed now.
If you have done the upgrade the following should work:
modelBuilder.Entity<SomeEntity>()
.HasOptional(m => m.Parent)
.WithMany()
.Map(c => c.MapKey("Entity_Id"));

Categories

Resources