创建复合密钥实体框架

时间:2013-02-14 10:53:59

标签: c# entity-framework entity-framework-5 composite-key

很快,我想在我的表上创建复合键,保留主键,以提高sql server搜索性能。每当我搜索没有主键的实体(即一串GUID)时,性能问题就出现在200k数据表上。假设我有3个班级

public class Device{

    public int ID { get; set; } 
    public string UDID { get; set; }
    public string ApplicationKey { get; set; }
    public string PlatformKey { get; set; }

    public ICollection<NotificationMessageDevice> DeviceMessages { get; set; } 
}

public class NotificationMessageDevice { 

    [Column(Order = 0), Key, ForeignKey("NotificationMessage")]
    public int NotificationMessage_ID { get; set; }

    [Column(Order = 1), Key, ForeignKey("Device")]
    public int Device_ID { get; set; }

    public virtual Device Device { get; set; }
    public virtual NotificationMessage NotificationMessage { get; set; }
}

public class NotificationMessage { 

    public int ID { get; set; }
    public string Text { get; set; }
    public DateTime CreateDate { get; set; }
}

        modelBuilder.Entity<Device>().HasKey(t => new { t.ID, t.ApplicationKey, t.PlatformKey, t.UDID });

问题在于,每当我想使用modelBuilder将ID,UDID,ApplicationKey和PlatformKey定义为复合键时,它会产生以下错误。

  

NotificationMessageDevice_Device_Target_NotificationMessageDevice_Device_Source:   :a中从属角色和主要角色中的属性数量   关系约束必须相同

我认为问题是因为NotificationMessageDevice上的导航属性无法识别Device表上的主键。我该如何解决这个问题?除此之外,如果您分享改善Entity框架搜索性能的经验,我将很高兴。通常,只要我使用没有主键的First方法,就会出现性能问题。

1 个答案:

答案 0 :(得分:76)

如果 Device 表具有复合主键,则 NotificationMessageDevice 表中需要相同的复合外键。 SQL如何在没有完整主键的情况下找到Device?您还应将这些字段作为 NotificationMessageDevice 表主键的一部分。否则,您无法保证主键是唯一的:

public class NotificationMessageDevice
{
    [Column(Order = 0), Key, ForeignKey("NotificationMessage")]
    public int NotificationMessage_ID { get; set; }

    [Column(Order = 1), Key, ForeignKey("Device")]
    public int Device_ID { get; set; }
    [Column(Order = 2), Key, ForeignKey("Device")]
    public string Device_UDID { get; set; }
    [Column(Order = 3), Key, ForeignKey("Device")]
    public string Device_ApplicationKey { get; set; }

    public virtual Device Device { get; set; }
    public virtual NotificationMessage NotificationMessage { get; set; }
}