0

首先让我为冗长的帖子道歉。我认为提供更多详细信息将有助于您了解情况。

我正在尝试使用 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 可以有多个 Alarms。而且,一个 ReasonActionDefinition 可以有多个 ReasonAction。Alarm 和 ReasonAction 之间存在隐式关系(即,一个 Alarm 可以有多个 ReasonAction)。这是我最麻烦的地方。

POCO

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; }
}

数据库上下文

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());
    }
}

流利的映射

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. 我需要如何更改我的代码以使一对多关系在警报和 ReasonAction 表(这样当我查询警报时,ReasonActions 导航属性会填充所有相关记录)?,C. 还有其他建议吗?

谢谢!!!

4

1 回答 1

-1

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

于 2012-10-03T17:35:32.177 回答