100 votes

Code First: Associations indépendantes vs associations de clés étrangères?

J'ai un mental débat avec moi à chaque fois que je commence à travailler sur un nouveau projet et je suis en train de concevoir mon POCOs. J'ai vu de nombreux tutoriels/des exemples de code qui semblent favoriser les associations de clé étrangère:

Clé étrangère de l'association

public class Order
{
    public int ID { get; set; }
    public int CustomerID { get; set; } // <-- Customer ID
    ...
}

Par opposition à des associations indépendantes:

Association indépendante

public class Order
{
    public int ID { get; set; }
    public Customer Customer { get; set; } // <-- Customer object
    ...
}

J'ai travaillé avec NHibernate dans le passé, et utilisé des associations indépendantes, qui non seulement se sentir plus OO, mais aussi (avec lazy loading) ont l'avantage de me donner accès à l'ensemble de la Clientèle de l'objet, au lieu de son ID. Cela me permet de, par exemple, de récupérer une Commande de l'instance et ensuite faire Order.Customer.FirstName sans avoir à faire une jointure explicite, ce qui est extrêmement pratique.

Bref, mes questions sont les suivantes:

  1. Existe-il des inconvénients significatifs dans l'aide des associations indépendantes? et...
  2. Si il n'y a pas tout, ce qui serait la raison de l'utilisation de la clé étrangère associations à tous?

106voto

Ladislav Mrnka Points 218632

Si vous voulez profiter pleinement de l'ORM, vous aurez certainement l'utilisation de l'Entité de référence:

public class Order
{
    public int ID { get; set; }
    public Customer Customer { get; set; } // <-- Customer object
    ...
}

Une fois que vous générez un modèle d'entité à partir d'une base de données avec FKs il sera toujours générer des références d'entité. Si vous ne voulez pas les utiliser, vous devez modifier manuellement le fichier EDMX et ajouter des propriétés représentant FKs. Au moins c'était le cas dans l'Entity Framework v1 où seuls des associations Indépendantes ont été autorisés.

Entity framework v4 propose un nouveau type d'association, appelé clé Étrangère de l'association. La différence la plus évidente entre l'indépendance et la clé étrangère de l'association est dans l'Ordre de la classe:

public class Order
{
    public int ID { get; set; }
    public int CustomerId { get; set; }  // <-- Customer ID
    public Customer Customer { get; set; } // <-- Customer object
    ...
}

Comme vous pouvez le voir vous avez à la fois FK de la propriété et de l'entité de référence. Il y a plus de différences entre les deux types d'associations:

Association indépendante

  • Il est représenté comme objet séparé en ObjectStateManager. Il a sa propre EntityState!
  • Lors de la construction d'association, vous avez toujours besoin d'entités à partir des deux extrémités de l'association
  • Cette association est représentée de la même manière qu'entité.

Clé étrangère de l'association

  • Il n'est pas représenté comme objet séparé en ObjectStateManager. En raison de cela, vous devez suivre quelques règles spéciales.
  • Lors de la construction d'association, vous n'avez pas besoin de les deux extrémités de l'association. Il suffit d'avoir de l'entité enfant et PK de l'entité mère mais PK valeur doit être unique. Donc, lorsque vous utilisez les clés étrangères de l'association, vous devez également attribuer temporaire des Id uniques nouvellement créées, les entités utilisées dans les relations.
  • Cette association n'est pas mappé mais au lieu de cela, il définit des contraintes référentielles.

Si vous souhaitez utiliser des clés de l'association, vous devez cocher Inclure les colonnes de clé étrangère dans le modèle dans le Modèle de Données d'Entité de l'Assistant.

Edit:

J'ai trouvé que la différence entre ces deux types d'associations n'est pas très connu donc j'ai écrit un court article traite de ce avec plus de détails et de ma propre opinion à ce sujet.

33voto

Seth Paulson Points 468

Utilise les deux. Et rendez vos références d'entités virtuelles pour permettre un chargement paresseux. Comme ça:

 public class Order
{
  public int ID { get; set; }
  public int CustomerID { get; set; }
  public virtual Customer Customer { get; set; } // <-- Customer object
  ...
}
 

Cela vous évite des recherches inutiles dans la base de données, permet un chargement paresseux et vous permet de voir / définir facilement l'ID si vous savez ce que vous voulez. Notez qu'avoir les deux ne change en rien la structure de votre table.

8voto

Yuliam Chandra Points 7324

Association indépendante ne fonctionne pas bien avec AddOrUpdate qui est habituellement utilisé en Seed méthode. Lorsque la référence est un élément existant, il sera ré-inséré.

// Existing customer.
var customer = new Customer { Id = 1, Name = "edit name" };
db.Set<Customer>().AddOrUpdate(customer);

// New order.
var order = new Order { Id = 1, Customer = customer };
db.Set<Order>().AddOrUpdate(order);

Le résultat est déjà client sera ré-inséré et la nouvelle (ré-inséré), le client sera associé à nouvel ordre.


Que si nous utilisons la clé étrangère de l'association et d'attribuer l'id.

 // Existing customer.
var customer = new Customer { Id = 1, Name = "edit name" };
db.Set<Customer>().AddOrUpdate(customer);

// New order.
var order = new Order { Id = 1, CustomerId = customer.Id };
db.Set<Order>().AddOrUpdate(order);

Nous avons le comportement attendu, de la clientèle existante sera associé à nouvel ordre.

4voto

Carnotaurus Points 1861

Je privilégie l'approche objet pour éviter les recherches inutiles. Les objets de propriété peuvent être tout aussi facilement remplis lorsque vous appelez votre méthode factory pour générer l'entité entière (à l'aide d'un simple code de rappel pour les entités imbriquées). Je ne vois aucun inconvénient, à l'exception de l'utilisation de la mémoire (mais vous mettriez vos objets en cache, non?). Vous ne faites donc que substituer la pile à la pile et tirer un gain de performances en ne effectuant pas de recherches. J'espère que cela a du sens.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X