【问题标题】:Entity Framework Cascade Delete (Inheritance)实体框架级联删除(继承)
【发布时间】:2020-08-27 22:47:27
【问题描述】:

我已经阅读了我能找到的所有内容,但我仍然无法解决我的问题。我正在使用 PostgreSQL,我有一个抽象类和一个子类。我希望在删除父级时也删除所有相关的依赖项。

这是我的班级的样子:

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);
}

我的孩子班:

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

还有短信正文

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; }
}

在 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);
  }

我不明白我做错了什么。该表被标记为级联,但是当我尝试删除它时它根本不起作用。有人可以给我一些关于如何设置的提示吗?

==== 稍后编辑

我有一个用于删除的通用仓库(模板参数是 NotificationModel 抽象类)

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);
    }
}

【问题讨论】:

  • 你的意思是删除某个对象的实例?你如何删除对象?
  • 嗨@Pribina。当我从表实体 SmsNotification 中删除时,我还想删除 SMSBody 详细信息。对于对象删除,我有一个通用存储库和删除方法:_context.NotificationsModel.Remove(object)。我不知道我是否从抽象类表中删除了一个问题(NotificationModel 而不是 SmsNotificationModel 女巫是音乐会类)。感谢重播。
  • 你在打电话给_context.Save()吗?
  • @VRoxa 是的。这也无济于事(没有错误,没有警告,保存上下文也很好)它所做的只是删除父类(NotificationModel),它不会进一步转到 SmsNotificationModel。
  • 我明白了。你的SmsBody 必须有一个Notification 属性,可以调用... HasOne(em =&gt; em.Body).WithOne(body =&gt; body.Notification /* or whatever you call this new property */);。您可以阅读更多关于此here 的信息。另外,别忘了Add-MigrationUpdate Database

标签: c# postgresql entity-framework-core


【解决方案1】:

应用于后期场景的一对一关系配置。
实体定义。

短信通知

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

短信正文

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; }
}

另外,顺便说一句,我上课了public。我不确定这是否重要,因为我相信 Entity Framework 需要从它自己的程序集访问我们的程序集。

然后,配置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);
        });
    }
}

还有,为了完成,数据访问层。
我不知道通用约束是否符合 Entity Framework 政策。我相信如果有的话。
我只是想提一下我要走的路。

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

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

    void Save();
}

我喜欢有一个定义所有 CRUD 操作的接口。甚至是 IAsyncRepository,它定义了相同的操作,但异步。

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);
    }
}

如果您遇到任何问题,您可以继续阅读extended explanation

希望对你有帮助。

【讨论】:

  • 感谢您抽出宝贵时间 Roxa。我终于按照你的建议解决了这个问题。
猜你喜欢
  • 2016-04-06
  • 2014-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多