【问题标题】:Entity Framework: three way many-many-one relationship with Fluent API?实体框架:与 Fluent API 的三向多对一关系?
【发布时间】:2016-09-21 19:43:58
【问题描述】:

试图理解这种关系并弄清楚如何使用流利的 api 映射它。

我有三个对象;请求、响应和管理员

一个请求可以有多个响应,来自一个或多个管理员

一个响应可以与一个请求和一个管理员相关联。

管理员可以与许多响应和许多请求相关联

从逻辑上讲,管理员被分配到一个请求,并且可以创建与分配给他们的请求相关联的响应。我意识到架构明智的管理员可以创建对未分配给他们的请求的响应,但这在应用程序中作为业务规则强制执行,除非有一种干净的方式来强制执行我并不真正关心的架构。

到目前为止,我看到的是以下(简化的)对象:

请求:

public class Request {
    public Guid Id {get;set;}
    public virtual ICollection<Response> Responses {get;set;}
    public virtual ICollection<Administrator> Administrators {get;set;}
}

回复:

public class Response {
    public Guid Id {get;set;} 
    public virtual Request { get;set;}
    public virtual Administrator { get;set;}
}

管理员:

public class Administrator {
   public Guid Id {get;set;}
   public virtual ICollection<Request> Requests {get;set;}
   public virtual ICollection<Response> Responses {get;set;}
}

我觉得这比我想象的要简单。但是,如果有人可以帮助我为此翻译流畅的 api 映射,那就太好了! :)

编辑:

一直在摆弄这个,我想我可能已经确定了一个解决方案:

响应有两个必需的请求和管理员映射

public class Response: EntityTypeConfiguration<Response>
{
    public ResponseMap()
    {

        HasKey(response => response.Id);

        HasRequired(e => e.Request);
        HasRequired(e => e.Administrator);
    }
}

请求与响应具有多对一关系,与具有关系表的管理员具有多对多关系:

public class RequestMap : EntityTypeConfiguration<Request>
{
    public RequestMap()
    {

        HasKey(r => r.Id);

        HasMany(e => e.Responses)
            .WithRequired(e => e.Request)
            .WillCascadeOnDelete(false);

        HasMany(or => or.Administrators)
            .WithMany(p => p.Requests)
            .Map(mc =>
            {
                mc.ToTable("RequestAdministrator");
                mc.MapLeftKey("RequestId");
                mc.MapRightKey("AdministratorId");
            });


    }
}

并且管理员与响应具有多对一的关系。它也与请求有关系,但在上面的映射中定义。

public class AdministratorMap : EntityTypeConfiguration<Administrator>
{
    public AdministratorMap()
    {
        HasKey(e => e.Id);

        HasMany(p => p.Responses)
            .WithRequired(o => o.Administrator)
            .WillCascadeOnDelete(false);

    }
}

我不能 100% 确定这是正确的做法,但乍一看似乎很合适。

【问题讨论】:

    标签: c# entity-framework ef-fluent-api


    【解决方案1】:

    我用下面的代码用这个数据库图生成了一个数据库:

    class Program
    {
        static void Main(string[] args)
        {
            Context context = new Context();
            context.Database.Initialize(true);
        }
    }
    
    public class Request
    {
        public int RequestId { get; set; }
        public virtual ICollection<Response> Responses { get; set; }
        public virtual ICollection<Administrator> Administrators { get; set; }
    }
    
    public class Response
    {
        public int ResponseId { get; set; }
        public virtual Request Request { get; set; }
        public virtual Administrator Administrator { get; set; }
    }
    
    public class Administrator
    {
        public int AdministratorId { get; set; }
        public virtual ICollection<Request> Requests { get; set; }
        public virtual ICollection<Response> Responses { get; set; }
    }
    
    public class Context : DbContext
    {
        public Context()
        {
            Database.SetInitializer(new DropCreateDatabaseAlways<Context>());
        }
    
        public DbSet<Request> Requests { get; set; }
        public DbSet<Response> Responses { get; set; }
        public DbSet<Administrator> Administrators { get; set; }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
    
            modelBuilder.Configurations.Add(new RequestsConfig());
            modelBuilder.Configurations.Add(new AdministratorsConfig());
            base.OnModelCreating(modelBuilder);
        }
    }
    
    public class RequestsConfig : EntityTypeConfiguration<Request>
    {
        public RequestsConfig()
        {
            HasMany(r => r.Responses).WithRequired(rs => rs.Request);
            HasMany(r => r.Administrators).WithMany(a => a.Requests);
        }
    }
    
    public class AdministratorsConfig: EntityTypeConfiguration<Administrator>
    {
        public AdministratorsConfig()
        {
            HasMany(a => a.Responses).WithRequired(r => r.Administrator);
        }
    }
    

    【讨论】:

    • 对,这就是我已经拥有的。我试图找出这个结构的 Fluent API 映射。
    • 我用我可能已经找到的可能解决方案编辑了原始帖子。结果表与您的图表完全相同。
    • 我在答案中添加了fluent api配置类
    • 那么responsemap上的hasrequired不是必须的吗?否则类似于我最终的结果。似乎也适用于测试,因此我将其标记为答案。 :) 谢谢你帮我想清楚。
    • 我最初有一个带有两个 hasrequired 表达式的响应配置类。连接表消失了。因此,我删除了它们,并且效果很好。
    【解决方案2】:
    public class Request
    {
      public int RequestId { get; set; }
      public virtual ICollection<Response> Responses { get; set; }
      public virtual ICollection<Administrator> Administrators { get; set; }
    }
    
    public class Response
    {
    public int ResponseId { get; set; }
    [ForeignKey("Request")]
    public virtual int? RequestID {get;set;}
    public virtual Request Request{get;set;}
    [ForeignKey("Administrator ")]
    public virtual int? AdministratorID {get;set;}
    public virtual Administrator Administrator { get; set; }
    }
    
    public class Administrator
    {
    public int AdministratorId { get; set; }
    public virtual ICollection<Request> Requests { get; set; }
    public virtual ICollection<Response> Responses { get; set; }
    }
    

    【讨论】:

      【解决方案3】:
      This is what you want
      
      [Table("REQUEST", Schema = "YourSchema")]
      public class REQUEST
      {
      
          public REQUEST()
          {
              Responses = new HashSet<RESPONSE>();
              Administrators = new HashSet<ADMINISTRATOR>();
          }
      
          [Column("REQUESTID")]
          public int RequestId { get; set; }
      
          public virtual ICollection<RESPONSE> Responses { get; set; }
          public virtual ICollection<ADMINISTRATOR> Administrators { get; set; }
      }
      
      [Table("RESPONSE", Schema = "YourSchema")]
      public class RESPONSE
      {
          [Column("RESPONSEID")]
          public int ResponseId { get; set; }
      
          [Column("REQUESTID")]
          public int RequestId { get; set; }
      
          [Column("ADMINISTRATORID")]
          public int AdministratorId { get; set; }
      
          [ForeignKey("RequestId")]
          public virtual REQUEST Request { get; set; }
      
          [ForeignKey("AdministratorId")]
          public virtual ADMINISTRATOR Administrator { get; set; }
      }
      
      [Table("ADMINISTRATOR", Schema = "YourSchema")]
      public class ADMINISTRATOR
      {
          public ADMINISTRATOR()
          {
              Requests = new HashSet<REQUEST>();
              Responses = new HashSet<RESPONSE>();
          }
          [Column("ADMINISTRATORID")]
          public int AdministratorId { get; set; }
      
          public virtual ICollection<REQUEST> Requests { get; set; }
          public virtual ICollection<RESPONSE> Responses { get; set; }
      }
      
          public DbSet<REQUEST> Requests { get; set; }
          public DbSet<RESPONSE> Responses { get; set; }
          public DbSet<ADMINISTRATOR> Administrators { get; set; }
      

      【讨论】:

        【解决方案4】:

        我相信您采用了正确的方法,将集合用于每个请求和响应的模型(多对多关系)。考虑将每个多对一关系应用于单独的部分类,以增加粒度和关注点分离。

        namespace ManyToManyToOneMessage
        {
            public partial class Message 
            {
                public Guid Id { get; set; }
                public virtual ICollection<Response> Responses { get; set; }
                public virtual ICollection<Administrator> Administrators { get; set; }
            }
        
            public partial class Message
            {
                public Request Request {get; set;}
                public Administrator Administrator { get; set;}
            }
        
            public class Response
            {
                //Place response formatting here.
            }
        
            public class Request
            {
                //Place request formatting here.
            }
        
            public class Administrator  {
                public Guid Id { get; set; }
                public virtual ICollection<Request> Requests { get; set; }
                public virtual ICollection<Response> Responses { get; set; }
            }   
        }
        

        这只是一条消息,带有请求和响应。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-08-04
          • 1970-01-01
          • 1970-01-01
          • 2016-07-01
          • 1970-01-01
          • 2013-11-24
          • 1970-01-01
          相关资源
          最近更新 更多