有两个类,它们是从单个基类继承的(我认为这是不相关的),对应于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对象,这些对象由RequiredNavigationPropertyConfiguration。WithMany()调用返回。但是由于这里没有太多关系...