使用Fluent API自定义外键关系

时间:2013-05-16 13:06:55

标签: c# entity-framework ef-code-first entity-framework-5 fluent-interface

我正在使用VS 2012和EF 5.0进行项目。

我有两张桌子:

public class AttendanceRecord
{
    public int Id { get; set; }

    public DateTime RecordedDate { get; set; }

    public DateTime SwipeDate { get; set; }

    public AttendanceStatus AttendanceStatus { get; set; }

    public VerificationMethod VerificationMethod { get; set; }

    public int MemberId { get; set; }

    public virtual Member Member { get; set; }
}

public class Member
{
    public int Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public DateTime Dob { get; set; }

    public string Address { get; set; }

    public string Ssn { get; set; }

    public string ContactNumber { get; set; }

    public int MemberUniqueId { get; set; }

    public virtual ICollection<AttendanceRecord> AttendanceRecords { get; set; }
}

在上下文类中,我重写了OnModelCreating以使用Fluent API定义关系:

    protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
    {
        // Overriding conventions through configuration
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Entity<Member>().Property(m => m.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        modelBuilder.Entity<DeviceConfigData>().HasRequired(d => d.Device).WithMany().HasForeignKey(a => a.DeviceID);
        modelBuilder.Entity<AttendanceRecord>().HasRequired(d => d.Member).WithMany(c => c.AttendanceRecords).HasForeignKey(a => a.MemberId);
    }

通过这种映射,我可以为会员表中的相应成员输入AttendanceRecord。一切正常......

我想要实现的是,而不是使用Member表中的MemberId主键来映射AttendanceRecord表中的关系,我想使用Member表的MemberUniqueId列。问题似乎是满足外键约束,引用的键必须是引用表中的主键。

我尝试了许多解决方案,例如.Map(c =&gt; c.MemberUniqueId)和其他一些但没有运气。

我认为在我们想要建立这种关系的常见情况下(不会出于各种原因使用主键,例如控制创建)。

请建议更正或替代方法。


更新

作为一种解决方法,我能够实现这一点,使得成员表的Id和MemberUniqueId列的复合键如下:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Composite primary key
        modelBuilder.Entity<Member>()
        .HasKey(d => new { d.Id, d.MemberUniqueId });

        modelBuilder.Entity<Member>().Property(m => m.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        modelBuilder.Entity<AttendanceRecord>()
            .HasRequired(d => d.Member)
            .WithMany(c => c.AttendanceRecords)
            .HasForeignKey(d => new { d.MemberId, d.MemberUniqueId });

        base.OnModelCreating(modelBuilder);
    } 

并在OnModelBinding()方法中定义外键关系,如下所示

    protected override void Seed(EftDbContext context)
    {
        // To define an index for the MemberUniqueId key to satisfy the foriegn key constraint
        context.Database.ExecuteSqlCommand("CREATE UNIQUE NONCLUSTERED INDEX IX_Members_MemberUniqueId ON dbo.Members ( MemberUniqueId )");

        // Other seed data code here...
    }

这种方法允许我创建一个成员表条目,获取MemberUniqueId并为具有此值的成员配置设备,当设备发送考勤数据时,它会发送可用于与Member关联的MemberUniqueId值。

更新2:

我在OnModelCreating中添加了一个额外的行来生成Id密钥数据库,我可以看到为Id列自动生成的值,就像Id是唯一的主键一样。

0 个答案:

没有答案