首先使用EF代码映射复合键

时间:2013-11-05 15:16:01

标签: c# sql-server entity-framework entity-framework-6

Sql server table:

SomeId PK varchar(50) not null 
OtherId PK int not null

我应该如何在EF 6代码中首先映射它?

public class MyTable
{
    [Key]
    public string SomeId { get; set; }

    [Key]
    public int OtherId { get; set; }
}

我已经看到了一些必须为每列设置顺序的示例,是否需要?

这个地方有官方文件吗?

4 个答案:

答案 0 :(得分:154)

你肯定需要输入列顺序,否则SQL Server应该知道哪一个先行?以下是您在代码中需要执行的操作:

public class MyTable
{
  [Key, Column(Order = 0)]
  public string SomeId { get; set; }

  [Key, Column(Order = 1)]
  public int OtherId { get; set; }
}

您还可以查看this SO question。如果您需要官方文档,我建议您查看official EF website。希望这会有所帮助。

编辑:我刚刚从Julie Lerman发现了一篇博文,其中包含了各种EF 6善良的链接。您可以找到所需的任何内容here

答案 1 :(得分:27)

对于使用Entity框架映射Composite主键,我们可以使用两种方法。

1)通过覆盖OnModelCreating()方法

例如:我有一个名为VehicleFeature的模型类,如下所示。

public class VehicleFeature
{
    public int VehicleId { get; set; }
    public int FeatureId{get;set;}
    public Vehicle Vehicle{get;set;}
    public Feature Feature{get;set;}
}

我的DBContext中的代码就像是,

public class VegaDbContext : DbContext
{
    public DbSet<Make> Makes{get;set;}

    public DbSet<Feature> Features{get;set;}
    public VegaDbContext(DbContextOptions<VegaDbContext> options):base(options)        
    {           

    }
    // we override the OnModelCreating method here.
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<VehicleFeature>().HasKey(vf=> new {vf.VehicleId, vf.FeatureId});
    }
}

2)按数据注释。

public class VehicleFeature
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]  
    [Key]
    public int VehicleId { get; set; }
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]   
    [Key]
    public int FeatureId{get;set;}
    public Vehicle Vehicle{get;set;}
    public Feature Feature{get;set;}
}

请参阅以下链接以获取更多信息。

1)https://msdn.microsoft.com/en-us/library/jj591617(v=vs.113).aspx

2)How to add a composite unique key using EF 6 Fluent Api?

答案 2 :(得分:6)

通过配置,您可以执行以下操作:

Model1
{
    int fk_one,
    int fk_two
}

Model2
{
    int pk_one,
    int pk_two,
}

然后在上下文配置

public class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Model1>()
            .HasRequired(e => e.Model2)
            .WithMany(e => e.Model1s)
            .HasForeignKey(e => new { e.fk_one, e.fk_two })
            .WillCascadeOnDelete(false);
    }
}

答案 3 :(得分:3)

我认为我会补充这个问题,因为它是Google搜索结果中排名最高的。

正如评论中所指出的那样,在EF Core中,不支持使用注释(键属性),并且必须使用流利的语言。

当我正在进行从EF6到EF Core的大规模迁移时,这并不好用,因此我尝试通过使用Reflection查找Key属性并在OnModelCreating期间应用它来对其进行破解

// get all composite keys (entity decorated by more than 1 [Key] attribute
foreach (var entity in modelBuilder.Model.GetEntityTypes()
    .Where(t => 
        t.ClrType.GetProperties()
            .Count(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(KeyAttribute))) > 1))
{
    // get the keys in the appropriate order
    var orderedKeys = entity.ClrType
        .GetProperties()
        .Where(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(KeyAttribute)))
        .OrderBy(p => 
            p.CustomAttributes.Single(x => x.AttributeType == typeof(ColumnAttribute))?
                .NamedArguments?.Single(y => y.MemberName == nameof(ColumnAttribute.Order))
                .TypedValue.Value ?? 0)
        .Select(x => x.Name)
        .ToArray();

    // apply the keys to the model builder
    modelBuilder.Entity(entity.ClrType).HasKey(orderedKeys);
}

我还没有在所有情况下都对它进行全面的测试,但是它在我的基本测试中仍然有效。希望这对某人有帮助