创建复合键实体框架

Posted

技术标签:

【中文标题】创建复合键实体框架【英文标题】:Creating Composite Key Entity Framework 【发布时间】:2013-01-30 03:46:10 【问题描述】:

简而言之,我想在保留主键的表上创建复合键,以提高 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: : 依赖角色和主体角色中的属性数量 关系约束必须相同

我认为问题在于 NotificationMessageDevice 上的导航属性无法识别 Device 表上的主键。我该如何解决这个问题?除此之外,如果您分享您提高实体框架搜索性能的经验,我将很高兴。通常,每当我使用不带主键的 First 方法时,都会出现性能问题。

【问题讨论】:

我对 EF 开发不太感兴趣,但你的 ForeignKeyAttribute 不是写错了吗? 【参考方案1】:

如果 Device 表有复合主键,那么您的 NotificationMessageDevice 表上需要相同的复合外键。 SQL如何找到没有完整主键的设备?此外,您应该使这些字段成为 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; 

【讨论】:

每当我们使用设备对象作为导航属性时,我们需要实现复合键上定义的所有属性是否必须在目标表中实现。 是的,这将是数据库中的外键。外键是父表的主键,所以应该完全一样。顺便说一句,如果您希望 PlatformKey 成为设备 PK 的一部分,您还需要 NotificationMessageDevice 中的该字段 嗯还有一个问题,那么有没有办法在实体框架上创建超级键? @kkocabiyik 据我所知,不,没有超级键 @kkocabiyik & SergeyBerezovskiy SQL PK 和 UNIQUE NOT NULL 声明超级键。 PK 的关系含义是您为此选择的某个 CK,而 CK 是不包含更小的 CK 的超级密钥。 SQL 允许声明包含较小值的 PK 或 UNIQUE NOT NULL。

以上是关于创建复合键实体框架的主要内容,如果未能解决你的问题,请参考以下文章

实体框架存在部分自动生成的复合键问题

实体框架:如何从具有复合键的表中返回一行?

使用实体框架将行插入到具有复合键的表中

如何在实体框架中为复合主键的特定列创建外键

代码优先实体框架或 NHibernate

Spring Boot:如何使用复合键创建实体