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

C# 首先使用EF代码映射复合键,c#,sql-server,entity-framework,entity-framework-6,C#,Sql Server,Entity Framework,Entity Framework 6,Sql server表: 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; } } 我见过一些例子,你必须为每一列设置顺序,这是必需的吗 有关于这方面的官方文档

Sql server表:

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; }
}
我见过一些例子,你必须为每一列设置顺序,这是必需的吗


有关于这方面的官方文档吗?

您肯定需要按列顺序排列,否则SQL Server怎么知道哪一个先到?以下是您需要在代码中执行的操作:

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

  [Key, Column(Order = 1)]
  public int OtherId { get; set; }
}
你也可以看看。如果你想要官方文件,我建议你看看。希望这有帮助


编辑:我刚找到朱莉·勒曼的一篇博文,上面有各种EF 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);
    }
}
公共类MyContext:DbContext
{
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.HasRequired(e=>e.Model2)
.WithMany(e=>e.Model1s)
.HasForeignKey(e=>new{e.fk_one,e.fk_two})
.WillCascadeOnDelete(假);
}
}

对于使用实体框架映射复合主键,我们可以使用两种方法

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)

我想我会补充这个问题,因为它是谷歌搜索结果中最热门的

如评论中所述,在EF Core中不支持使用注释(键属性),必须使用fluent完成

当我正在进行从EF6到EF Core的大规模迁移时,这是不令人满意的,因此我尝试通过使用反射来查找键属性,然后在onmodel创建期间应用它

// 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);
}

我还没有在所有情况下完全测试过它,但它在我的基本测试中都有效。希望这有助于某人

SomeId
字符串还是
int
?@IronMan84这是一个字符串,我会解决它。如何通过EntityConfiguration实现这一点?我实际上没有连接表的实体。。。我只有两个实体,其中一个实体上有一个EntityConfiguration,上面有一个.Map()来设置映射。
否则SQL Server怎么知道哪一个先到?
-为什么它不知道其他列的顺序?EF不知道其他列的顺序,只要指定了名称,就可以按任意顺序插入with列。如果EF需要复合PK的顺序,那么它必须与索引相关。@Davor我想EF创建者可以使用反射来推断键/列顺序,但不这样做可能会有性能方面的考虑。我会在任何一天,特别是在我的DAL中,考虑到设计时间的特殊性,而不是较慢的性能。我认为提前订购是有意义的。如果有一天你对这些属性重新排序,你会发现实体框架停止工作,你会非常生气。在上下文配置中的什么地方?如果你是通过使用Fluent API的代码配置上下文。公共类MyContext:DbContext{protected override void OnModelCreating(DbModelBuilder modelBuilder){modelBuilder.Entity().HasRequired(e=>e.Model2)。带有多个(e=>e.Model1s)。HasForeignKey(e=>new{e.fk_one,e.fk_two})。WillCascadeOnDelete(false);}}我发现我必须在dotnet core.FYI上使用ModelBuilder而不是DbModelBuilder。对于EF core,选项#2是,“只能使用流畅的API配置组合键-约定永远不会设置组合键,并且不能使用数据注释来配置组合键。”
// 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);
}