将EF代码优先映射到现有数据库

时间:2012-08-23 15:44:38

标签: entity-framework ef-code-first

首先让我为冗长的帖子道歉。我想更多的细节可以帮助你了解情况。

我正在尝试使用EF 5 Code First开发应用程序的数据层,并将所有内容映射到现有数据库。我想使用DbContext,POCO,流畅的表映射等,但我们现有的数据库(表)不是直截了当的。所以,我遇到了一些问题。我现在试着简要介绍一下情况,然后再问几个问题。

AlarmDefinition
AlarmDefinitionID int (primary key) (is identity)
...

Alarm
AlarmID int (primary key) (is identity)
AlarmDefinitionID int (sort of a foreign key) (is nullable)
SampleTagID int (is nullable)
SampleTime DateTime (is nullable)
...

ReasonAction
Time DateTime (primary key)
TagID int (primary key)
ReasonActionID int (primary key)

ReasonActionDefinition
ReasonActionID int (primary key) (is identity)
...

因此,一个AlarmDefinition可以有很多警报。并且,一个ReasonActionDefinition可以有许多ReasonActions。 Alarm和ReasonAction之间存在隐式关系(即,一个Alarm可以有许多ReasonAction)。这是我遇到最多麻烦的地方。

波苏斯

AlarmDefinition
public class AlarmDefinition
{
    public int AlarmDefinitionID { get; set; }
    ...
    public virtual ICollection<Alarm> Alarms { get; set; }
}

Alarm
public class Alarm
{
    public int AlarmID { get; set; }
    public Nullable<int> SampleTagID { get; set; }
    public Nullable<System.DateTime> SampleTime { get; set; }
    ...
    public Nullable<int> AlarmDefinitionID { get; set; }
    public virtual AlarmDefinition AlarmDefinition { get; set; }
    // I don’t know if this is set up correctly
    public virtual ICollection<ReasonAction> ReasonActions { get; set; }
}

ReasonAction
public class ReasonAction
{
    public System.DateTime Time { get; set; }
    public int TagID { get; set; }
    public virtual Alarm Alarm { get; set; }
    public int ReasonActionID { get; set; }  // Primary key
    public virtual ReasonActionDefinition ReasonActionDefinition { get; set; }
}

ReasonActionDefinition
public class ReasonActionDefinition
{
    public int ReasonActionID { get; set; }
    ...
    public virtual ICollection<ReasonAction> ReasonActions { get; set; }
}

的DbContext

public class AppDbContext : DbContext
{
    public DbSet<Alarm> Alarms { get; set; }
    public DbSet<AlarmDefinition> AlarmDefinitions { get; set; }
    public DbSet<ReasonAction> ReasonActions { get; set; }
    public DbSet<ReasonActionDefinition> ReasonActionDefinitions { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new AlarmMap());
        modelBuilder.Configurations.Add(new AlarmDefinitionMap());
        modelBuilder.Configurations.Add(new ReasonActionMap());
        modelBuilder.Configurations.Add(new ReasonActionDefinitionMap());
    }
}

Fluent Mappings

AlarmDefinitionMap
public class AlarmDefinitionMap : EntityTypeConfiguration<AlarmDefinition>
{
    public AlarmDefinitionMap()
    {
        this.HasKey(t => t.AlarmDefinitionID);
        ...
        this.ToTable("AlarmDefinition");
        this.Property(t => t.AlarmDefinitionID).HasColumnName("AlarmDefinitionID");
        ...
    }
}

AlarmMap
public class AlarmMap : EntityTypeConfiguration<Alarm>
{
    public AlarmMap()
    {
        this.HasKey(t => t.AlarmID);
        ...
        this.ToTable("Alarm");
        this.Property(t => t.AlarmID).HasColumnName("AlarmID");
        this.Property(t => t.AlarmDefinitionID).HasColumnName("AlarmDefinitionID");
        this.Property(t => t.SampleTagID).HasColumnName("SampleTagID");
        this.Property(t => t.SampleTime).HasColumnName("SampleTime");
        ...
        this.HasOptional(t => t.AlarmDefinition)
            .WithMany(d => d.Alarms)
            .HasForeignKey(t => t.AlarmDefinitionID);
    }
}

ReasonActionMap
public class ReasonActionMap : EntityTypeConfiguration<ReasonAction>
{
    public ReasonActionMap()
    {
        this.HasKey(t => new { t.Time, t.TagID, t.ReasonActionID });
        this.Property(t => t.TagID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        this.Property(t => t.ReasonActionID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        this.ToTable("ReasonAction");
        this.Property(t => t.Time).HasColumnName("Time");
        this.Property(t => t.TagID).HasColumnName("TagID");
        this.Property(t => t.ReasonActionID).HasColumnName("ReasonActionID");
        // Relationships
        // Not sure if this is correct since the related column names in the Alarm table are SampleTagId, not TagID and SampleTime, not Time.  And SampleTagID and SampleTime in the Alarm table are not a primary keys.
        // There's an implicit one-to-many relationship between the Alarm and ReasonAction entities.
        this.HasRequired(t => t.Alarm)
            .WithMany(d => d.ReasonActions)
            .HasForeignKey(t => new { t.TagID, t.Time });
        this.HasRequired(t => t.ReasonActionDefinition)
            .WithMany(d => d.ReasonActions)
            .HasForeignKey(t => t.ReasonActionID);
    }
}

ReasonActionDefinitionMap
public class ReasonActionDefinitionMap : EntityTypeConfiguration<ReasonActionDefinition>
{
    public ReasonActionDefinitionMap()
    {
        this.HasKey(t => t.ReasonActionID);
        ...
        this.ToTable("ReasonActionDefinition");
        this.Property(t => t.ReasonActionID).HasColumnName("ReasonActionID");
        ...
    }
}

呼!那是很多东西。无论如何,我们的数据库存在一些问题,并将事物映射到EF:1。没有声明性参照完整性 - 全部在触发器或遗留应用程序代码中处理,2。在Alarm表中,SampleTagID和SampleTime不是主键,但这两列是与ReasonAction表的隐式一对多关系的单方面,3。Alarms和ReasonAction表之间的列名不匹配(Alarm表的SampleTagID和SampleTime以及ReasonAction表的Time和TagID)。

所以,我的问题是:A。鉴于上述情况,我可以使EF代码首先使用我现有的数据库和表吗?B。如何更改我的代码以实现一对多Alarm和ReasonAction表之间的关系工作(这样当我查询Alarms时,ReasonActions导航属性会填充所有相关记录)?,C。还有其他任何建议吗?

感谢!!!

1 个答案:

答案 0 :(得分:-1)

我们最终放弃了EF并编写了我们自己的自定义ADO.NET代码。