4

J'utilise d'abord le code EF5 dans une application de test simple pour tester diverses fonctions. J'ai défini une «relation d'identification» entre deux entités qui représentent un lien un-à-plusieurs. Ici, je définis une PhotoCollection qui a beaucoup d'entités Photo enfant;Comment définir les relations d'identification imbriquées Entity Framework code

public class PhotoCollection 
{ 
    public int Id { get; set; } 
    public virtual ISet<Photo> Photos { get; private set; } 

    public PhotoCollection() 
    { 
     Photos = new HashSet<Photo>(); 
    } 
} 

public class Photo 
{ 
    [Key, ForeignKey("Parent"), Column(Order = 1)] 
    public int PhotoCollectionId { get; set; } 

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

    public virtual PhotoCollection Parent { get; set; } 


    [Required, MaxLength(200)] 
    public string FilePath { get; set; } 

    public Photo() 
    { 
    } 

} 

et mon implémentation de OnModelCreating inclut;

modelBuilder.Entity<Photo>().Property(p => p.PhotoId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

Le résultat est que lorsque je supprime un PhotoCollection, toutes les entités photos sont supprimées et qui est fourni par la « relation d'identification ». Génial.

Ma question est comment puis-je définir un niveau supplémentaire dans ce graphique d'objet, disons que je veux un PhotoProperties comme une collection un-à-plusieurs de Photo. Dans ce cas, je voudrais supprimer PhotoCollection et tous les enregistrements Photo et PhotoProperty appropriés seront également supprimés. En utilisant l'approche ci-dessus, ne serait-il pas nécessaire d'ajouter une propriété GrandParent à PhotoProperty qui pointait vers la PhotoCollection? Puis-je obtenir le même résultat en utilisant l'API Api dans le constructeur du modèle?

Les seuls exemples que j'ai réussi à trouver en ligne concernent les hiérarchies parent> enfant à un seul niveau.

Merci d'avance.

Répondre

8

À mon avis cela devrait fonctionner:

public class Photo 
{ 
    [Key, ForeignKey("Parent"), Column(Order = 1)] 
    public int PhotoCollectionId { get; set; } 

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

    public virtual PhotoCollection Parent { get; set; } 

    public virtual ISet<PhotoProperty> PhotoProperties { get; private set; } 

    //... 
} 

public class PhotoProperty 
{ 
    [Key, ForeignKey("Parent"), Column(Order = 1)] 
    public int PhotoCollectionId { get; set; } 

    [Key, ForeignKey("Parent"), Column(Order = 2)] 
    public int PhotoId { get; set; } 

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

    public virtual Photo Parent { get; set; } 

    //... 
} 

Notez que PhotoCollectionId dans PhotoProperty ne se réfère pas à une PhotoCollection mais fait partie du composite (PhotoCollectionId,PhotoId) clé étrangère qui fait référence à Photo.

Et oui, vous pouvez définir la mise en correspondance avec l'ensemble API Courant:

modelBuilder.Entity<PhotoCollection>() 
    .HasMany(pc => pc.Photos) 
    .WithRequired(p => p.Parent) 
    .HasForeignKey(p => p.PhotoCollectionId); 

modelBuilder.Entity<Photo>() 
    .HasKey(p => new { p.PhotoCollectionId, p.PhotoId }); 

modelBuilder.Entity<Photo>() 
    .Property(p => p.PhotoId) 
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

modelBuilder.Entity<Photo>() 
    .HasMany(p => p.PhotoProperties) 
    .WithRequired(pp => pp.Parent) 
    .HasForeignKey(pp => new { pp.PhotoCollectionId, pp.PhotoId }); 

modelBuilder.Entity<PhotoProperty>() 
    .HasKey(pp => new { pp.PhotoCollectionId, pp.PhotoId, pp.PhotoPropertyId }); 

modelBuilder.Entity<PhotoProperty>() 
    .Property(pp => pp.PhotoPropertyId) 
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
+0

Merci beaucoup cela fonctionne parfaitement. –

+0

C'était utile. Connaissez-vous une bonne documentation pour cela? J'essaie de faire quelque chose de similaire pour Azure Mobile Services et Azure SQL. – WiteCastle

Questions connexes