【问题标题】:EF6 mapping many-to-many using same column nameEF6 使用相同的列名进行多对多映射
【发布时间】:2020-01-04 20:22:45
【问题描述】:

在现有的 sqlite 数据库中,我有 3 个表。
首先是一个带有 `events` 的表,它使用 `id` 和 `licence_key` 的复合主键。
第二个表包含 `codes`,这也使用了 `session_code` 和 `licence_key` 的组合键。
最终表是来自以下 sql 的关联表:

CREATE TABLE `event_code` (
    `event_id`  INTEGER NOT NULL,
    `session_code`      TEXT NOT NULL,
    `licence_key`   TEXT NOT NULL,
    CONSTRAINT `event_code$event_id_session_code_licence_key_PK` PRIMARY KEY(`event_id` ASC,`session_code` ASC,`licence_key` ASC),
    CONSTRAINT `event_code$event_id_licence_key_FK` FOREIGN KEY(`event_id`, `licence_key`) REFERENCES `event`(`id`, `licence_key`) ON UPDATE CASCADE ON DELETE CASCADE,
    CONSTRAINT `event_code$session_code_licence_key_FK` FOREIGN KEY(`session_code`, `licence_key`) REFERENCES `code`(`session_code`, `licence_key`) ON UPDATE CASCADE ON DELETE CASCADE
);

我的程序使用实体框架和流畅的映射来加载和存储这些表中的对象。
在 EF6 中,我认为映射的相关部分应如下所示:

modelBuilder.Entity<EF6EventInformation>().HasMany(eventInfo => eventInfo.InternalSessionCodes).WithMany().Map(mapping =>
            {
                mapping.ToTable("event_code");
                mapping.MapLeftKey("event_id", "licence_key");
                mapping.MapRightKey("session_code", "licence_key");
            });

但是,这会引发异常:

System.Data.Entity.ModelConfiguration.ModelValidationException: One or more validation errors were detected during model generation:

licence_key: Name: Each property name in a type must be unique. Property name 'licence_key' is already defined.

看来我不能重复使用同一列。
当然,我可以更改数据库设计并将两个实体的 licence_key 存储在各自单独的列中,但因为每个 licence_keys 的值总是必须匹配另一个,这似乎不是特别有用。

有什么方法可以正确设置此映射而无需更改我的数据库设计?

【问题讨论】:

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


    【解决方案1】:

    这似乎是通过隐式连接表在多对多上的 EF6 映射的限制。

    可以在不更改数据库结构的情况下映射关系,但通过添加显式连接实体并将多对多映射为两个多对一来更改实体模型。

    所以你需要一个这样的实体:

    public class EventCode
    {
        public int event_id { get; set; }
        public int session_code { get; set; }
        public int license_key { get; set; }
        public Event Event { get; set; }
        public Code Code { get; set; }
    }
    

    然后将现有的集合导航属性更改为如下内容:

    public ICollection<EventCode> EventCodes { get; set; }
    

    并像这样使用流畅的配置:

    modelBuilder.Entity<EventCode>()
        .ToTable("event_code");
    modelBuilder.Entity<EventCode>()
        .HasKey(e => new { e.event_id, e.session_code, e.license_key });
    modelBuilder.Entity<EventCode>()
        .HasRequired(e => e.Event)
        .WithMany(e => e.EventCodes)
        .HasForeignKey(e => new { e.event_id, e.license_key });
    modelBuilder.Entity<EventCode>()
        .HasRequired(e => e.Code)
        .WithMany()
        .HasForeignKey(e => new { e.session_code, e.license_key });
    

    当然,您可以创建更好的 C# 常规属性名称

    public class EventCode
    {
        public int EventId { get; set; }
        public int SessionCode { get; set; }
        public int LicenseKey { get; set; }
        public Event Event { get; set; }
        public Code Code { get; set; }
    }
    

    并将它们映射到现有的表列名

    但这并没有从根本上改变关系映射解决方案。

    modelBuilder.Entity<EventCode>()
        .ToTable("Event_Code");
    modelBuilder.Entity<EventCode>()
        .HasKey(e => new { e.EventId, e.SessionCode, e.LicenseKey });
    modelBuilder.Entity<EventCode>().Property(e => e.EventId)
        .HasColumnName("event_id");
    modelBuilder.Entity<EventCode>().Property(e => e.SessionCode)
        .HasColumnName("session_code");
    modelBuilder.Entity<EventCode>().Property(e => e.LicenseKey)
        .HasColumnName("license_key");
    modelBuilder.Entity<EventCode>()
        .HasRequired(e => e.Event)
        .WithMany(e => e.EventCodes)
        .HasForeignKey(e => new { e.EventId, e.LicenseKey });
    modelBuilder.Entity<EventCode>()
        .HasRequired(e => e.Code)
        .WithMany()
        .HasForeignKey(e => new { e.SessionCode, e.LicenseKey });
    

    多对多映射的两种方式各有利弊,但这里根本没有选择。

    【讨论】:

      猜你喜欢
      • 2012-06-22
      • 2017-08-05
      • 2011-06-28
      • 2013-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多