web-dev-qa-db-fra.com

Mapper deux entités différentes à la même table?

J'ai une table dans ma base de données avec beaucoup de champs. La plupart du temps, j'ai besoin de tous ces champs. Il y a un scénario, cependant, où je n'ai besoin que de quelques champs et je charge une tonne de lignes.

Ce que j'aimerais faire, c'est ajouter manuellement une entité, puis simplement la mapper à la table d'origine, mais supprimer les colonnes dont je n'ai pas besoin. J'ai tout réglé, mais j'obtiens l'erreur plutôt explicite de:

Problème de mappage des fragments ... Les entités EntitySets 'FmvHistoryTrimmed' et 'FMVHistories' sont toutes deux mappées sur la table 'FMVHistory'. Leurs clés primaires peuvent entrer en collision.

Y a-t-il une autre façon de procéder? Encore une fois, la plupart du temps, toutes les colonnes sont utilisées, donc je ne veux pas réduire l'entité d'origine et mettre les champs "supplémentaires" dans un type complexe.

39
Adam Rackis

Vous ne pouvez pas mapper deux entités régulières dans la même table. Vous avez plusieurs choix:

  1. Utilisez le fractionnement de table.
  2. Utiliser une requête personnalisée avec projection vers un type non entité (comme proposé par @Aducci)
  3. Utiliser QueryView
  4. Utiliser la vue de la base de données ou directement DefiningQuery

Fractionnement de table

Fractionnement de table vous permet de mapper une table en deux entités dans une relation 1: 1. La première entité ne contiendra que PK et un sous-ensemble de champs dont vous aurez toujours besoin. La deuxième entité contiendra tous les autres champs et PK. Les deux entités contiendront la propriété de navigation l'une à l'autre. Maintenant, si vous n'avez besoin que d'un sous-ensemble de champs, vous interrogerez la première entité. Si vous avez besoin de tous les champs, vous interrogerez la première entité et incluerez la propriété de navigation dans la deuxième entité. Vous pouvez également charger une seconde entité paresseuse si vous en avez besoin.

QueryView

QueryView est une requête ESQL définie directement dans votre mappage (MSL) et elle est mappée sur un nouveau type d'entité en lecture seule. Vous pouvez utiliser QueryView pour définir la projection de votre entité complète dans la sous-entité. QueryView doit être défini manuellement dans EDMX (il n'est pas disponible dans Designer). Comme je le sais, QueryView n'est pas disponible en premier dans Code mais c'est en fait la même chose que la projection personnalisée vers un type non entité.

DefiningQuery

DefiningQuery est une requête personnalisée définie directement dans votre modèle de stockage (SSDL). DefiningQuery est généralement utilisé lors du mappage vers des vues de base de données, mais vous pouvez l'utiliser pour n'importe quel SQL SELECT personnalisé. Vous mapperez le résultat de la requête au type d'entité en lecture seule. DefiningQuery doit être défini manuellement dans EDMX (il n'est pas disponible dans Designer). Il n'est pas non plus directement disponible dans Code en premier mais c'est en fait la même chose que d'appeler SqlQuery sur DbDatabase. Le problème avec DefiningQuery est qu'une fois que vous le définissez manuellement dans SSDL, vous ne pouvez pas utiliser le modèle de mise à jour de la base de données car cette opération remplace le SSDL complet et supprime la définition de votre requête.

34
Ladislav Mrnka

Je voudrais créer une vue sur la base de données contenant uniquement les données dont vous avez besoin et ajouter la vue à votre modèle de données d'entité.

Si vous ne souhaitez pas modifier la base de données, vous pouvez créer un Linq vers des entités ou une instruction ESQL projetant vers une classe POCO avec uniquement les informations dont vous avez besoin.

public IQueryable<SimpleObject> GetView(DBContext context)
{
    return  (from obj in context.ComplexObjects
            select new SimpleObject() { Property1 = obj.Property1,
                                        Property1 = obj.Property2
                                      }); 
}
8
Aducci