Type de complexe Entity Framework vs Création d'une nouvelle entité

.net .net-4.0 c# entity-framework

Question

Je lis à propos de Entity Framework 4.0 et je me demandais pourquoi créer un type complexe et non une nouvelle entité (table) et une relation entre eux

Réponse acceptée

L'exemple parfait est une adresse. L'utilisation d'un type complexe pour une adresse est beaucoup plus facile à gérer qu'une nouvelle entité. Avec les types complexes, vous n'avez pas à traiter avec la clé primaire. Pensez à accéder à une adresse pour savoir combien de types d'entités communs auraient une adresse (Business Units, People, Places). Imaginez que vous remplissiez plusieurs adresses et que vous deviez définir une clé pour chacune d'elles. Avec les types complexes, vous accédez simplement aux propriétés internes de leur type et vous avez terminé. Voici un lien MSDN d'un exemple. http://msdn.microsoft.com/en-us/library/bb738613.aspx


Réponse populaire

Cette question est déjà là depuis un moment déjà, mais je vais quand même ajouter une réponse dans l'espoir que le prochain pauvre sanglot qui se produit sache ce qu'il va faire.

Les types complexes ne prennent pas en charge le chargement différé, du moins pas dans EF 4.3. Prenons la situation de l'adresse comme exemple. Vous avez une table Personne avec 15 colonnes, dont 5 contiennent des informations d'adresse pour certaines personnes. Il a 50k enregistrements. Vous créez une entité Person pour la table avec un type complexe Address.

Si vous avez besoin d’une liste de noms de tous les individus de votre base de données, vous feriez

var records = context.Persons;

qui inclut également les adresses, pompant 5 * 50k valeurs dans votre liste sans raison et avec un retard perceptible. Vous pouvez choisir de ne charger que les valeurs dont vous avez besoin dans un type anonyme avec

var records = from p in context.Persons
              select new {
                LastName = p.LastName,
                FirstName = p.FirstName,
              }

ce qui fonctionne bien pour ce cas, mais si vous aviez besoin d'une liste plus complète avec, par exemple, 8 colonnes de non-adresse, vous devrez soit ajouter chacune d'elles dans le type anonyme, soit simplement aller avec le premier cas et retourner au chargement d'adresse inutile. Les données.

À propos des types anonymes: bien qu’ils soient très utiles au sein d’une même méthode, ils vous obligent à utiliser des variables dynamiques ailleurs dans votre classe ou vos enfants de classe, ce qui annule certaines fonctions de refactoring de Visual Studio et vous laisse exposé aux erreurs d’exécution. Idéalement, vous souhaitez faire circuler des entités parmi vos méthodes afin que ces entités transportent le moins de bagages possible. C'est pourquoi le chargement paresseux est si important.

En ce qui concerne l'exemple ci-dessus, les informations d'adresse doivent être réellement dans une table à part entière, recouverte d'une entité complète. De plus, si votre client demande une deuxième adresse pour une personne, vous pouvez l'ajouter à votre modèle en ajoutant simplement une référence d'adresse supplémentaire dans Personne.

Si, contrairement à l'exemple ci-dessus, vous avez réellement besoin des données d'adresse dans presque toutes les requêtes que vous effectuez et que vous souhaitez réellement que ces champs soient dans la table Personne, ajoutez-les simplement à l'entité Personne. Vous n’avez plus le préfixe d’adresse ordonné, mais ce n’est pas vraiment quelque chose à perdre pour dormir.

Mais attendez, il y a plus!

Les types complexes constituent un cas particulier, une bosse sur le paysage lisse des entités EF simples. Ceux de votre projet peuvent ne pas être éligibles pour hériter de votre classe de base d'entités, ce qui rend impossible leur utilisation par des méthodes traitant de vos entités en général.

Supposons que vous avez une classe de base d'entité nommée EntityModel qui définit un ID de propriété. Ceci est la clé pour tous vos objets d'entité, vous pouvez donc maintenant créer

class EntityModelComparer<T> : IEqualityComparer<T> where T : EntityModel

que vous pouvez ensuite utiliser avec Distinct () pour filtrer les doublons de tout type IQueryable de type T où T est une classe d’entité. Un type complexe ne peut pas hériter d'EntityModel car il ne possède pas de propriété ID, mais c'est correct, car vous ne l'utiliseriez pas de toute façon.

Plus loin dans la ligne, vous rencontrez une situation où vous avez besoin d'un moyen de passer par n'importe quelle entité et d'effectuer une opération. Vous souhaitez peut-être répertorier de manière dynamique les propriétés d'une entité sur l'interface utilisateur et laisser l'utilisateur y effectuer des requêtes. Donc, vous construisez une classe que vous pouvez instancier pour un type particulier et que vous lui confiez en entier:

public class GenericModelFilter<T> : where T : EntityModel

Oh, attendez, votre type complexe n'est pas de type EntityModel. Vous devez maintenant compliquer votre arborescence d'héritage d'entité pour prendre en charge des types complexes ou vous débarrasser du contrat EntityModel et réduire la visibilité.

Ensuite, vous ajoutez une méthode à votre classe qui, basée sur les sélections d'utilisateurs, peut créer une expression que vous pouvez utiliser avec linq pour filtrer toute classe d'entité.

Expression<Func<T, bool>> GetPredicate() { ... }

Alors maintenant, vous pouvez faire quelque chose comme ça:

personFilter = new GenericModelFilter<Person>();
companyFilter = new GenericModelFilter<Company>();
addressFilter = new GenericModelFilter<Address>(); //Complex type for Person

...

var query = from p in context.Persons.Where(personFilter.GetPredicate())
            join c in context.Companies.Where(companyFilter.GetPredicate()) on p.CompanyID = c.ID
            select p;

Cela fonctionne de la même manière pour tous les objets d'entité ... sauf Address avec ses besoins spécifiques. Vous ne pouvez pas faire de jointure comme vous l'avez fait avec Company. Vous pouvez y accéder depuis Personne, mais comment y appliquez-vous l'expression et restez-vous avec Personne à la fin? Vous devez maintenant prendre un moment et comprendre ce cas particulier pour un système simple qui fonctionne facilement partout ailleurs.

Ce modèle se répète tout au long du projet. Est-ce que je parle d'expérience? Je souhaite que je n'ai pas. Les types complexes continuent de freiner votre progression, comme un élève mal élevé au fond de la classe, sans rien ajouter d’essentiel. Faites-vous une faveur et optez pour des objets d'entité réels.



Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow