实体框架代码优先 - 多个FK到不同的父表

时间:2016-02-06 13:54:16

标签: c# entity-framework ef-code-first

看起来像是另一个EF多重FK"问题但请继续阅读。我有以下要求:

  • A" Monitor"可以有零个或多个" Notifier"
  • A" Monitor"可以有零个或多个"设置"
  • A"通知人"可以有零个或多个"设置"

所以,删除" Monitor"将删除它"设置"和#34;通知器"。此外,由于"通知器"可能有零个或多个设置,相关的"设置" s也应该被删除。

我已经创建了以下模型,但击中着名的" ...可能导致循环或多个级联路径"错误。

最接近的答案是Entity Framework Cascading Delete,但它使用数据库第一种方法。

有人可以建议一种解决方法来启用上述模型的级联删除吗?

这是我的模特:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Testbed
{
    public class Monitor
    {
        public int Id { get; set; }
        [Column(TypeName = "varchar")]
        [MaxLength(255)]
        public string Type { get; set; }
        [Column(TypeName = "varchar")]
        [MaxLength(20)]
        public string RunFrequency { get; set; }
        public List<Setting> Settings { get; set; }
        public List<Notifier> Notifiers { get; set; }
    }

    public class Setting
    {
        public int Id { get; set; }
        [MaxLength(255)]
        [Column(TypeName = "varchar")]
        public string Name { get; set; }
        [MaxLength(512)]
        public string Value { get; set; }
        public bool IsPassword { get; set; }
    }

    public class Notifier
    {
        public int Id { get; set; }
        [MaxLength(255)]
        [Column(TypeName = "varchar")]
        public string Name { get; set; }
        public List<Setting> Settings { get; set; }

    }
}

1 个答案:

答案 0 :(得分:0)

SettingNotifier课程中,您必须添加一些属性才能允许这种关系。

public class Setting
{
    public int Id { get; set; }
    [MaxLength(255)]
    [Column(TypeName = "varchar")]
    public string Name { get; set; }
    [MaxLength(512)]
    public string Value { get; set; }
    public bool IsPassword { get; set; }

    //Add these properties
    public int ForeignId{ get; set; }
    public virtual Monitor Monitor { get; set; }
    public virtual Notifier Notifier { get; set; }
}

public class Notifier
{
    public int Id { get; set; }
    [MaxLength(255)]
    [Column(TypeName = "varchar")]
    public string Name { get; set; }
    public List<Setting> Settings { get; set; }

    //Add these properties
    public int MonitorId { get; set; }
    public virtual Monitor Monitor { get; set; }

}

现在您已启用关系,您需要添加映射。如果您将它们分开,可以在EntityModel或映射类中完成此操作。

modelBuilder.Entity<Setting>()
    .HasOptional(e => e.Monitor) //Could be .HasRequired()
    .WithMany(e => e.Settings)
    .HasForeignKey(e => e.ForeignId)
    .WillCascadeOnDelete(true);

modelBuilder.Entity<Setting>()
    .HasOptional(e => e.Notifier) //Could be .HasRequired()
    .WithMany(e => e.Settings)
    .HasForeignKey(e => e.ForeignId)
    .WillCascadeOnDelete(true);

modelBuilder.Entity<Notifier>()
    .HasRequired(e => e.Monitor) //Could be .HasOptional()
    .WithMany(e => e.Notifiers)
    .HasForeignKey(e => e.MonitorId)
    .WillCascadeOnDelete(true);

设置方式总是会导致问题。您的Settings表正由多个表使用。在我的示例中,我在Settings中创建了一个由其他两个表使用的外键。如果您想进入MonitorIdNotifierId,也可以拆分。这一切都取决于您的数据模型。

编辑: 如果您需要MonitorIdNotifierId

modelBuilder.Entity<Setting>()
    .HasOptional(e => e.Monitor) //Could be .HasRequired()
    .WithMany(e => e.Settings)
    .HasForeignKey(e => e.MonitorId)
    .WillCascadeOnDelete(true);

modelBuilder.Entity<Setting>()
    .HasOptional(e => e.Notifier) //Could be .HasRequired()
    .WithMany(e => e.Settings)
    .HasForeignKey(e => e.NotifierId)
    .WillCascadeOnDelete(true);

您还必须将这些属性添加到Setting类。

public class Setting
{
    public int MonitorId { get; set; }
    public int NotifierId { get; set; }
}