0

I have read everything that I could find and still I couldn't solve my problem. I am using PostgreSQL and I have an abstract class and a child class. I would like that when the parent has been deleted also all related dependencies to be deleted.

Here is how my class looks like:

public abstract class NotificationModel
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Key]
    public Guid id { get; set; }
    public string type { get; set; }
    // and other common fileds
    public abstract NotificationModel buildObject(JObject json);
}

My child class :

class SmsNotificationModel : NotificationModel
{
    public override NotificationModel buildObject(JObject json){return dummyObj;}
    public SmsBody Body { get; set; }
    public Guid Fk_sms { get; set; }
}

And SmsBody

class SmsBody
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Key]
    public Guid Id { get; set; }
    public List<string> Recipients { get; set; }
    public string Route { get; set; }

    //edit
    public SmsNotificationModel smsNotModel { get; set; }
}

In DbContext:

 protected override void OnModelCreating(ModelBuilder modelBuilder)
 {
        modelBuilder.Entity<SmsNotificationModel>()
            .HasOne(em => em.Body)
            .WithOne(d => d.smsNotModel)
            .HasForeignKey<SmsNotificationModel>(f => f.Fk_sms)
            .OnDelete(DeleteBehavior.Cascade);

        base.OnModelCreating(modelBuilder);
  }

I don't understand what I am doing wrong. The table is marked as a cascade but when I try to drop this it does not work at all. Can somebody give me some tips about how can I set up this.

==== Later Edit

I have a generic repo for removing (template param is NotificationModel abstract class)

public class GenericRepository<T> : IGenericRepository<T> where T :class
{
    private readonly ApplicationDbContext _context;
    private DbSet<T> table = null;

    public GenericRepository(ApplicationDbContext _context) {
        this._context = _context;
        table = _context.Set<T>();
    }

    public void Delete(object id){
        T existing = table.Find(id);
        table.Remove(existing);
    }
}
8
  • by drop you mean delete instance of some object? how do you delete object? Commented May 12, 2020 at 7:52
  • Hi @Pribina. When I remove from table entity SmsNotification I want also to remove SMSBody details. For object removal, I have a generic repo and the delete method: _context.NotificationsModel.Remove(object). I don't know if is a problem that I am removing from the abstract class table (NotificationModel and not SmsNotificationModel witch is the concert class). Thanks for replay. Commented May 12, 2020 at 8:07
  • Are you calling _context.Save()? Commented May 12, 2020 at 8:16
  • @VRoxa yes. This also does not help (no error, no warning, all good also with save context) All it does is to remove the parent class (NotificationModel) it does not go further to SmsNotificationModel. Commented May 12, 2020 at 8:18
  • I see. Your SmsBody must have a Notification property, which to call ... HasOne(em => em.Body).WithOne(body => body.Notification /* or whatever you call this new property */);. You can read more about this here. Plus, don't forget to Add-Migration and Update Database. Commented May 12, 2020 at 8:23

1 Answer 1

1

One-to-One Relationship configuration applied to the post scenario.
Entities definition.

SmsNotification

public class SmsNotificationModel : NotificationModel
{
    public SmsBody Body { get; set; }
    // ...
}

SmsBody

public class SmsBody
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Key]
    public Guid Id { get; set; }
    // ...

    // I moved the Id relation here.
    // To me, it seems like Notification is the one-level-up absatraction model.
    // This may be changed at any time.
    public SmsNotificationModel SmsNotModel { get; set; }
    public Guid SmsNotificationModelId { get; set; }
}

Also, by the way, I made classes public. I am not sure if this is to important, by I believe that Entity Framework needs access from its own assembly to ours.

Then, configuring OnModelCreating.

public class YourContext : DbContext
{
    // ...

    public DbSet<SmsNotificationModel> Notifications { get; set; }
    public DbSet<SmsBody> SmsBodies { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        // ...

        builder.Entity<SmsNotificationModel>(entity =>
        {
            // Configures the One-To-One relationship
            // and the OnDelete behavior, as well.
            entity.HasOne<SmsBody>(notification => notification.Body)
                  .WithOne(body => body.SmsNotModel)
                  .HasForeignKey<SmsBody>(body => body.SmsNotificationModelId)
                  .OnDelete(DeleteBehavior.Cascade);
        });
    }
}

And, just for completion, the data-access layer.
I don't know if generic constrains fits with Entity Framework policies. I believe if does.
I just want to mention my way to go.

public interface IRepository<TEntity> : IDisposable
{
    // CRUD methods...

    void Delete(TEntity entity);
    void Delete(Expression<Func<TEntity, bool>> expression);

    void Save();
}

I like to have an interface defining all CRUD operations. Even an IAsyncRepository which defines the same operations, but async.

public class SmsRepository : IRepository<SmsNotificationModel>
{
    private readonly YourContext _context;

    public SmsRepository(YourContext context) =>  _context = context;

    // CRUD operations implementation ...

    public void Delete(SmsNotificationModel entity)
    {
        _context.Notifications.Remove(entity);
    }
}

You can continue reading an extended explanation if you face any truobles.

Hope it helps.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your time Roxa. I finally manage to fix this following your suggestion.

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.