web-dev-qa-db-fra.com

Mappage des clés composites à l'aide du code EF en premier

Table de serveur SQL:

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

Comment dois-je mapper cela en EF 6 en premier?

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

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

J'ai vu des exemples où vous devez définir l'ordre de chaque colonne, est-ce nécessaire?

Existe-t-il une documentation officielle à ce sujet quelque part?

98
loyalflow

Vous devez absolument mettre dans l'ordre des colonnes, sinon, comment SQL Server est-il censé savoir lequel commence en premier? Voici ce que vous devez faire dans votre code:

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

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

Vous pouvez également consulter this SO question . Si vous souhaitez une documentation officielle, je vous recommande de consulter le site Web officiel de EF . J'espère que cela aide.

EDIT: Je viens de trouver un article de blog de Julie Lerman avec des liens vers toutes sortes de qualités EF 6. Vous pouvez trouver tout ce dont vous avez besoin ici .

160
IronMan84

Pour mapper une clé primaire composée à l'aide du cadre Entity, nous pouvons utiliser deux approches.

1) en remplaçant la méthode OnModelCreating ()

Par exemple: j'ai la classe de modèle nommée VehicleFeature comme indiqué ci-dessous.

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

Le code dans mon DBContext serait,

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) Par les annotations de données.

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

Veuillez vous référer aux liens ci-dessous pour plus d'informations.

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

2) Comment ajouter une clé unique composite en utilisant EF 6 Fluent Api?

31
Krishna

Grâce à la configuration, vous pouvez faire ceci:

Model1
{
    int fk_one,
    int fk_two
}

Model2
{
    int pk_one,
    int pk_two,
}

puis dans la config de contexte

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

Je pensais ajouter quelque chose à cette question car il s’agit du premier résultat de recherche Google.

Comme indiqué dans les commentaires, dans EF Core, l'utilisation d'annotations (attribut Key) n'est pas prise en charge et doit être effectuée avec fluence.

Comme je travaillais sur une migration importante de EF6 vers EF Core, cela était peu recommandable et j'ai donc essayé de la pirater en utilisant Reflection pour rechercher l'attribut Key, puis l'appliquer pendant 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);
}

Je n'ai pas complètement testé cela dans toutes les situations, mais cela fonctionne dans mes tests de base. J'espère que cela aide quelqu'un

3
cmorgan091