使用组合键将单向1映射为零或一

时间:2018-10-12 16:00:24

标签: c# .net entity-framework sqlite fluent

有两个类,它们是从单个基类继承的(我认为这是不相关的),对应于sqlite数据库中的两个表。
这两个类均包含许可证密钥的值以及创建条目和最后更新条目的值。

还要注意的是,单个许可证可能具有与之关联的任意数量的事件,但是每个许可证只能定义一个事件以自动启动。同样,连接是单向的; autostart对象将始终引用事件,但并非所有事件都具有引用它们的autostart对象,并且所有事件都不知道它们是否是autostart事件。

类定义:

public abstract class EntityBase : IModel, ITimestampedEntity
{
    public virtual string LicenseKey { get; set; }
    public virtual DateTime? CreatedAt { get; set; }
    public virtual DateTime? UpdatedAt { get; set; }
}

public class Event : EntityBase, IEvent
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}

public class AutoStart : EntityBase
{
    public Event Event { get; set; }
}

我将为sqlite数据库中的两个表提供sql:

CREATE TABLE `event` (
  `id`  INTEGER NOT NULL,
  `name`    TEXT NOT NULL,
  `start_date`  TEXT,
  `end_date`    TEXT,
  `license_key` TEXT,
  `created_at`  TEXT,
  `updated_at`  TEXT,
  PRIMARY KEY(`id`,`license_key`)
);

CREATE TABLE `autostart_event` (
  `license_key` TEXT NOT NULL,
  `event_id`    INTEGER NOT NULL,
  `created_at`  TEXT,
  `updated_at`  TEXT,
  PRIMARY KEY(`license_key`),
  FOREIGN KEY(`license_key`) REFERENCES `event`(`license_key`) ON UPDATE CASCADE,
  FOREIGN KEY(`event_id`) REFERENCES `event`(`id`) ON UPDATE CASCADE
);

请注意,与EF6本身相比,我们使用的SQL遵循命名时间表更多。因此,在映射中定义了列名。

使用Entity Framework Fluent API映射表。上下文中定义的映射如下:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Fluent API event table mapping properties
    var eventMapping = modelBuilder.Entity<Event>().ToTable("event");
    eventMapping.HasKey(@event => new { @event.Id, @event.LicenseKey }).Property(@event => @event.Id).HasColumnName("id").HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    eventMapping.Property(@event => @event.Name).HasColumnName("name").IsRequired();
    eventMapping.Property(@event => @event.StartDate).HasColumnName("start_date");
    eventMapping.Property(@event => @event.EndDate).HasColumnName("end_date");
    eventMapping.Property(@event => @event.LicenseKey).HasColumnName("license_key");
    eventMapping.Property(@event => @event.CreatedAt).HasColumnName("created_at");
    eventMapping.Property(@event => @event.UpdatedAt).HasColumnName("updated_at");

    // Fluent API event_autostart table mapping properties
    var autoStartMapping = modelBuilder.Entity<AutoStart>().ToTable("autostart_event");
    autoStartMapping.HasKey(autoStart => autoStart.LicenseKey).Property(autoStart => autoStart.LicenseKey).HasColumnName("license_key");
    autoStartMapping.HasRequired(autoStart => autoStart.Event).WithRequiredPrincipal().Map(map => map.MapKey("event_id"));
    autoStartMapping.Property(autoStart => autoStart.CreatedAt).HasColumnName("created_at");
    autoStartMapping.Property(autoStart => autoStart.UpdatedAt).HasColumnName("updated_at");
}

如此处所示,事件表具有一个组合的主键索引,该索引由id和license_key组成。
一个自动启动对象只有一个主键:license_key(因为每个许可证只能定义一个自动启动事件)。

我能够从数据库中保存和检索事件,但是保存自动启动对象时会引发异常,说明:

SQL logic error foreign key mismatch - "autostart_event" referencing "event"

我认为这是由于组合键和非默认列名(毕竟,列名是event_id而不是event),但是,我一直无法找到如何正确映射列名一对一或零一关系。
documentation引用了HasForeignKey()方法,但这仅适用于DependentNavigationPropertyConfiguration对象,这些对象由RequiredNavigationPropertyConfigurationWithMany()调用返回。但是由于这里没有太多关系...

0 个答案:

没有答案