Delete from Entity Framework dynamically with relationship tables - c#

I have tables with foreign keys from main tables. I want that when I'm deleting an entry also want to be able to first remove all related entities from other tables.
I tried this
public void Delete<T>(T entity) where T : EntityBase
{
var relationManager = ((IObjectContextAdapter)m_context).ObjectContext.ObjectStateManager.GetRelationshipManager(entity);
var related = relationManager.GetAllRelatedEnds();
foreach (var relate in related)
{
// what to do here - ??
}
}
EntryBase is a base DBSet entity for all tables in DB contains UId as GUID type - the relationship is by this GUID

you can do it automatically using small configuration using FluentAPI in onModelCreating Method by add OnDelete(DeleteBehavior.Cascade) example as below
modelBuilder.Entity<YourEntity>(entity =>
{
entity.HasOne(d => d.Entity1)
.WithMany(p => p.YourEntity)
.HasForeignKey(d => d.Id)
.OnDelete(DeleteBehavior.Cascade) //This is the key to solve your problem
.HasConstraintName("FK_YourEntity_Entity1");
}

Related

Xamarin Forms, EF Core 5 and SQLite: Join table of Many-To-Many is not being cleared when deleting

The join table of a many-to-many relationship in my Xamarin.Forms application seems to not be cleared correctly when deleting one of the two entities.
I have these classes:
public class Input
{
// One-to-many
public ObservableCollection<InputResult> InputResults { get; set; }
//...
// Here are many more entities which shouldn't be relevant for this example
//...
}
public class InputResult
{
// One-to-many
public string ParentInputId { get; set;}
// Many-to-many
public ObservableCollection<MyDropdown> MyDropdowns { get; set; }
}
public class MyDropdown
{
// Many-to-many
public ObservableCollection<InputResult> InputResults { get; set; }
}
I configured the relationships in my DbContext class like this:
modelBuilder.Entity<Input>()
.HasMany(b => b.InputResults)
.WithOne()
.HasForeignKey(b => b.ParentInputId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<InputResult>()
.HasMany(b => b.MyDropdowns)
.WithMany(b => b.InputResults);
Let's say I have previously loaded an Input with its InputResults. Then I delete the InputResults in a helper class like that:
Context.RemoveRange(Input.InputResults);
The InputResults get deleted correctly. When I look into the SQLite database directly I still see all the entries in the join table of InputResults and MyDropdown. Why are there still entries? Yesterday one of our users got a unique constraint error after deleting some data and trying to insert the same data again.
I appreciate any help.
Edit:
To expand my comment on CSharp's answer:
I can't use OnDelete(DeleteBehavior.Cascade) when configuring the DbContext. It seems as EF Core did this correctly by itself though. The part of the join table in the DatabaseContextModelSnapshot.cs looks like this:
modelBuilder.Entity("InputResultMyDropdown", b =>
{
b.HasOne("Inputs.MyDropdown", null)
.WithMany()
.HasForeignKey("MyDropdownId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Inputs.InputResult", null)
.WithMany()
.HasForeignKey("InputResultId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
There should be a cascade delete behavior in DbContext:
modelBuilder.Entity<InputResult>()
.HasMany(b => b.MyDropdowns)
.WithMany(b => b.InputResults)
.OnDelete(DeleteBehavior.Cascade);

Entity Framework relationships not loading

I generated my DbContext and entity types using the Scaffold-DbContext command in powershell.
I can successfully retrieve records from the database however, the relationships always seem to be null.
Asset.cs
class Asset
{
[ForeignKey("CategoryId")]
public virtual AssetCategory Category { get; set; } = null!;
}
The relationship configuration appears to be OK in the DbContext file that was automatically generated.
entity.HasOne(d => d.Category)
.WithMany(p => p.Assets)
.HasForeignKey(d => d.CategoryId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_Asset_AssetCategory");
What I do note is that the Constraints folder within the database for the Asset table is empty?
Example usage
// basic properties of asset are correctly hydrated here, just not relationships
var asset = await _dbContext.Assets.FindAsync(id);
// category is always null
var category = asset.Category;
This happens with all the relationships defined on the entity model and I don't understand why?
Thanks to the comments from DavidG pointing out I needed to use the Include method to load the relationship(s) as they are not automatically lazy loaded.
var asset = _dbContext.Assets
.Where(a => a.id == id)
.Include(a => a.Category)
.FirstOrDefaultAsync();

Configure Auto Generated Table in Entity Framework

i am having troubles trying to figure out how to rename and configure an autogenerated table, from entity framework.
Here is my code :
public class ApplicationUser : IdentityUser
{
public virtual List<ApplicationUser> AddingFriends { get; set; }
public virtual List<ApplicationUser> AddedFriends { get; set; }
}
There result expressed by those entities once migrate to the database is as the following :
So i basically just want to rename this table and it's columns names.
Besides that i also want to create a second table for bloqued people wich would have the same lists of entities. So basically when i add two other lists of application users it binds those property to this actual table shown below.
Is there a way to control those table generation and configure them correctly?
Thanks in advance. Cheers.
You are using code first approach and this keeps track of the model and database table corresponding to that model.So, You cannot change the model.Options are to enable migration or to disable model checking.
check this link for migrationhttps://learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/migrations-and-deployment-with-the-entity-framework-in-an-asp-net-mvc-application
After looking at the Fluent API Documentation i found that i could configure that with by adding those lines of code to OnModelCreating method:
modelBuilder.Entity<ApplicationUser>()
.HasMany(c => c.AddedFriends)
.WithMany(c => c.AddingFriends)
.Map(m =>
{
m.ToTable("Friends");
m.MapLeftKey("AddedUser");
m.MapRightKey("AddingUser");
});
modelBuilder.Entity<ApplicationUser>()
.HasMany(c => c.BloquedUsers)
.WithMany(c => c.BloquingUsers)
.Map(m =>
{
m.ToTable("Bloqueds");
m.MapLeftKey("BloquingUser");
m.MapRightKey("BloquedUser");
});
Thanks for your answers.

How to configure EF6 multiple indepdendent code-first 1:1 unidirectional mappings?

I would like to configure two entities to have independent unidirectional 1:1 mappings using Code First Fluent API. But I am struggling to get the correct configuration (even though my schema looks right).
Models;
class User {
Guid Id;
virtual Subscription ActiveSubscription;
}
class Subscription {
Guid Id;
virtual User Owner;
}
In this relationship, Subscription.Owner should be NOT NULL but User.ActiveSubscription should be NULLABLE.
There can be many Subscription for the same User, with 0..1 of those referenced as the User.ActiveSubscription.
I'm using the following EntityTypeConfiguration implementations, but I am unable to INSERT both objects.
class UserMap : EntityTypeConfiguration<User> {
HasOptional(x => x.ActiveSubscription)
.WithOptionalDependent()
.Map(m => m.MapKey("ActiveSubscription_Id"))
.WillCascadeOnDelete(false);
}
class SubscriptionMap : {
HasRequired(x => x.Owner)
.WithOptional()
.Map(m => m.MapKey("Owner_Id"))
.WillCascadeOnDelete(true);
}
Deleting a User should CASCADE DELETE to Subscription table, though this should not be the case for the inverse relationship.
After generating a schema from this mapping, it looks correct, but I get errors on INSERT ("Unable to determine a valid ordering for dependent operations.")

Issue with many to many relationship in code first c#

I am using entity framework code first for creating database in my project. I have defined many to many relationship between following two table.:
Student
Course
Fluent Api
modelBuilder.Entity<Student>().HasMany(e => e.Courses)
.WithMany(e => e.Students).Map(m =>
{
m.MapLeftKey("StudentId");
m.MapRightKey("CourseId");
m.ToTable("StudentCourse");
});
This will define a many to many relationship between Student and Course and will create a new table StudentCourse in the database.
Now i want to define a new relationship (that may be 1 to 1 OR 1 to many) between
StudentCource
Any other table
How can i do this with entity framework code first ??
What do you want is no possible without creating a own class (poco) for the StudentCourse
public class StudentCourse
{
public int Id {get;set;}
public Student Student {get; set;}
public Course Course {get; set;}
}
And then use fluent api to make the relationship between this three variables
modelBuilder.Entity<StudentCourse>()
.HasRequired(i => i.Student)
.WithMany(u => u.StudentCourses)
.HasForeignKey(i => i.StudentId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<StudentCourse>()
.HasRequired(i =>i.Course)
.WithMany(d =>d.StudentCourses)
.HasForeignKey(i => i.CourseId)
.WillCascadeOnDelete(false);
Where StudentCourses are the navigation properties in the student class and Course class
You can use the Id defined as primary key or use the foreign key of both tables as primary:
modelBuilder.Entity<StudentCourse>()
.HasKey(i => new {i.StudentId,i.CourseId });
In my opinion use the Id as primary key make you more simple the things for making relationships between StudentCourse and another table.

Categories