【问题标题】:Deleting an entity with a one to many relationship on two levels result in a foreign key exception在两个级别上删除具有一对多关系的实体会导致外键异常
【发布时间】:2015-12-20 14:24:37
【问题描述】:

您好,我正在尝试从该数据库中删除一个在两个级别上具有一对多关系的实体。我正在使用实体框架 6。

这是模块的可能数据库图:

这是我的代码:

public partial class DatabaseContext : DbContext
{
    public DatabaseContext()
        : base("name=DatabaseContext")
    {
    }
          public virtual DbSet<Property> Properties { get; set; }
    public virtual DbSet<PropertyCategory> PropertyCategories { get; set; }
    public virtual DbSet<TemplateProperty> TemplateProperties { get; set; }
    public virtual DbSet<TemplateProperyCategory> TemplateProperyCategories { get; set; }
    public virtual DbSet<Template> Templates { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Property>()
        .HasMany(e => e.TemplateProperties)
        .WithRequired(e => e.Property)
        .WillCascadeOnDelete(false);

    modelBuilder.Entity<PropertyCategory>()
        .HasMany(e => e.TemplateProperyCategories)
        .WithRequired(e => e.PropertyCategory)
        .WillCascadeOnDelete(true);

    modelBuilder.Entity<TemplateProperyCategory>()
        .HasMany(e => e.TemplateProperties)
        .WithRequired(e => e.TemplateProperyCategory)
        .HasForeignKey(e => e.TemplatePropertyCategoryId)
        .WillCascadeOnDelete(true);

    modelBuilder.Entity<Template>()
        .HasMany(e => e.TemplateProperyCategories)
        .WithRequired(e => e.Template)
        .WillCascadeOnDelete(true);
    }
}


public class TemplateService : ITemplateService
{
    private readonly ITemplateUnitOfWork templateUnitOfWork;

    public TemplateService(ITemplateUnitOfWork templateUnitOfWork)
    {
        this.templateUnitOfWork = templateUnitOfWork;
    }

    public void Delete(TemplateDTO templateDTO)
    {
        var template = templateUnitOfWork.TemplateRepository.GetById(templateDTO.Id);
        templateUnitOfWork.TemplateRepository.Delete(template);
        templateUnitOfWork.SaveChanges();
    }
}

public class BaseUnitOfWork
{
    protected DatabaseContext DatabaseContext;

    public void SaveChanges()
    {

        bool saveFailed;
        do
        {
            saveFailed = false;
            try
            {
                DatabaseContext.SaveChanges();
                DatabaseContext.Dispose();
            }
            catch (DbUpdateConcurrencyException ex)
            {
                saveFailed = true;
                ex.Entries.Single().Reload();
            }

        } while (saveFailed);
    }
}

public class TemplateUnitOfWork : BaseUnitOfWork, ITemplateUnitOfWork
{
    private IRepository<Template> templateRepository;

    public TemplateUnitOfWork(DatabaseContext databaseContext)
    {
        DatabaseContext = databaseContext;
    }


    public IRepository<Template> TemplateRepository
    {
        get
        {
            return templateRepository ?? (templateRepository =
                Injector.ResolverService.Resolve<IRepository<Template>>(DatabaseContext));
        }
    }

}

public class Repository<T> : IRepository<T> where T : class
{
    protected readonly DatabaseContext DatabaseContext;

    protected readonly DbSet<T> DbSet;

    public Repository(DatabaseContext databaseContext)
    {
        DatabaseContext = databaseContext;
        DbSet = DatabaseContext.Set<T>();
        DatabaseContext.Configuration.ValidateOnSaveEnabled = false;
    }

    public void Delete(T entity)
    {
        DbEntityEntry dbEntityEntry = DatabaseContext.Entry(entity);
        if (dbEntityEntry.State != EntityState.Deleted)
        {
            dbEntityEntry.State = EntityState.Deleted;
        }
        else
        {
            DbSet.Attach(entity);
            DbSet.Remove(entity);
        }
    }

    public virtual T GetById(int id)
    {
        return DbSet.Find(id);
    }
}

我希望能够从表 Templates 中删除一个元素。发生这种情况时,我希望它从 TemplatePropertyCategories 中删除与其相关的所有元素以及在 TemplatePRperties 和 TemplatePropertyCategories 之间具有关系的所有元素。

databaseContext 是使用 Visual Studios Code First 从数据库工具生成的。

当我加载模板实体时,它预加载了 templatePropertyCategories 和 templateProperties。

我认为为了使其正常工作,必须为空闲表设置 WillCascadeDelete(true),但这并没有做任何可见的事情。

当我尝试运行这段代码时,我得到了这个异常:

DELETE 语句与 REFERENCE 约束“FK_dbo.TemplateProperties_dbo.Templates_TemplateId”冲突。数据库 \"TElectronics\"、表 \"dbo.TemplateProperyCategories\"、列 'TemplateId' 中发生冲突。\r\n语句已终止。"}

更改数据库的结构不是一种选择。

有谁知道我怎样才能做到这一点?

【问题讨论】:

    标签: c# entity-framework entity-framework-6


    【解决方案1】:

    您忘记配置 TemplateProperty 实体

    modelBuilder.Entity<TemplateProperty>()
        .HasRequired(t => t.TemplatePropertyCategory)
        .WithMany(t => t.TemplateProperties)
        .HasForeignKey(d => d.TemplatePropertyCategoryId)
        .WillCascadeOnDelete(true);
    

    【讨论】:

      猜你喜欢
      • 2019-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多