【问题标题】:How do I map a composite primary key in Entity Framework 4 code first?如何首先在 Entity Framework 4 代码中映射复合主键?
【发布时间】:2011-02-13 13:33:23
【问题描述】:

我首先掌握了 EF4 代码,并且到目前为止我很喜欢它。但我无法将实体映射到具有复合主键的表。

我试过的配置是这样的:

public SubscriptionUserConfiguration()

    {
                Property(u => u.SubscriptionID).IsIdentity();
                Property(u => u.UserName).IsIdentity();
    }

抛出此异常: 无法推断实体类型“SubscriptionUser”的键。

我错过了什么?

【问题讨论】:

    标签: entity-framework orm composite-key


    【解决方案1】:

    我将尝试使用以下实体逐步解释它

    public class Account
    {
        public int AccountId1 { get; set; }
        public int AccountId2 { get; set; }
        public string Description { get; set; }
    }
    
    1. 创建一个派生自EntityTypeConfiguaration<TEntity> 对象的类以覆盖约定

      class AccountEntityTypeConfiguration : EntityTypeConfiguration<Account>
      {
      
          public AccountEntityTypeConfiguration()
          {
            // The Key
            // The description of the HasKey Method says
            // A lambda expression representing the property to be used as the primary key.
            // If the primary key is made up of multiple properties then specify an anonymous type including the properties.
            // Example C#: k => new { k.Id1, k.Id2 }
            // Example VB: Function(k) New From { k.Id1, k.Id2 }
            this.HasKey(k => new { k.AccountId1, k.AccountId2 } );  // The Key
      
            // Maybe the key properties are not sequenced and you want to override the conventions
            this.Property(p => p.AccountId1).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
            this.Property(p => p.AccountId2).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
      
            this.Property(p => p.Description).IsRequired();  // This property will be required
            this.ToTable("Account");  // Map the entity to the table Account on the database
          }
      }
      
    2. 创建派生自DbContext 对象的类时,覆盖OnModelCreating 方法并将新的AccountEntityTypeConfiguration 对象添加到模型生成器的配置中。

      public class MyModelAccount : DbContext
      {
          public DbSet<Account> Accounts { get; set;}
      
          protected override void OnModelCreating(DbModelBuilder modelBuilder)
          {
              // Add a new AccountEntityTypeConfiguration object to the configuration of the model, that will be applied once the model is created. 
              modelBuilder.Configurations.Add(new AccountEntityTypeConfiguration());
          }
      
      }
      

    希望对你有帮助!

    【讨论】:

      【解决方案2】:

      你也可以使用Column属性

      public class UserProfileRole
      {
          [Key, Column(Order = 0)]
          public int UserId { get; set; }
      
          [Key, Column(Order = 1)]
          public int RoleId { get; set; }
      }
      

      【讨论】:

      • 只是提醒那些搜索 - ColumnAttribute 需要 .NET 4.5
      【解决方案3】:

      你也可以使用

      HasKey(u => new { u.SubscriptionID, u.UserName });
      

      编辑:

      我发现的一个限制是以下不起作用:

      public ProjectAssignmentConfiguration()
      {
          HasKey(u => u.Employee.EmployeeId);
          HasKey(u => u.Project.ProjectId);
      }
      

      public ProjectAssignmentConfiguration()
      {
          HasKey(u => new { u.Employee.EmployeeId, u.Project.ProjectId });
      }
      

      那么如何设置一个实体,其中连接表的主键由外键组成?

      【讨论】:

      • 刚刚遇到了同样的问题,我的症状是它返回了正确数量的实体,但是所有具有相同第一个键的实体都返回了第一条记录的数据内容,而忽略了第二条。我的插入似乎也做了一些有趣的事情,并插入了数据库中已经存在的其他记录的数据。
      • 您可以将外键添加到实体上。例如,您可以将 Project 和 ProjectId 添加到父实体,而不是 u.Project.Id。
      【解决方案4】:

      解决了:我应该使用 HasKey,而不是 Identity。这有效:

      public SubscriptionUserConfiguration()
      {
           HasKey(u => u.SubscriptionID);
           HasKey(u => u.UserName);
      }
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-28
      • 1970-01-01
      相关资源
      最近更新 更多