Pour plusieurs raisons dont je n'ai pas la liberté de parler, nous définissons une vue sur notre base de données Sql Server 2005 comme ceci:
CREATE VIEW [dbo].[MeterProvingStatisticsPoint]
AS
SELECT
CAST(0 AS BIGINT) AS 'RowNumber',
CAST(0 AS BIGINT) AS 'ProverTicketId',
CAST(0 AS INT) AS 'ReportNumber',
GETDATE() AS 'CompletedDateTime',
CAST(1.1 AS float) AS 'MeterFactor',
CAST(1.1 AS float) AS 'Density',
CAST(1.1 AS float) AS 'FlowRate',
CAST(1.1 AS float) AS 'Average',
CAST(1.1 AS float) AS 'StandardDeviation',
CAST(1.1 AS float) AS 'MeanPlus2XStandardDeviation',
CAST(1.1 AS float) AS 'MeanMinus2XStandardDeviation'
WHERE 0 = 1
L'idée est que Entity Framework créera une entité basée sur cette requête, ce qu'il fait, mais il la génère avec une erreur indiquant ce qui suit:
Avertissement 6002: La table / vue 'Keystone_Local.dbo.MeterProvingStatisticsPoint' n'a pas de clé primaire définie. La clé a été déduite et la définition a été créée en tant que table / vue en lecture seule.
Et il décide que le champ CompletedDateTime sera la clé primaire de cette entité.
Nous utilisons EdmGen pour générer le modèle. Existe-t-il un moyen de ne pas inclure dans le cadre d'entité un champ de cette vue en tant que clé primaire?
la source
J'ai pu résoudre ce problème en utilisant le concepteur.
Je n'ai pas eu à modifier ma vue pour utiliser les solutions de contournement ISNULL, NULLIF ou COALESCE. Si vous mettez à jour votre modèle à partir de la base de données, les avertissements réapparaissent, mais disparaissent si vous fermez et rouvrez VS. Les modifications que vous avez apportées dans le concepteur seront conservées et ne seront pas affectées par l'actualisation.
la source
D'accord avec @Tillito, mais dans la plupart des cas, cela endommagera l'optimiseur SQL et n'utilisera pas les bons index.
Cela peut être évident pour quelqu'un, mais j'ai passé des heures à résoudre des problèmes de performances en utilisant la solution Tillito. Disons que vous avez la table:
et votre point de vue est quelque chose comme ça
L'optimiseur SQL n'utilisera pas l'index ix_customer et il effectuera une analyse de table sur l'index primaire, mais si au lieu de:
tu utilises
cela fera en sorte que MS SQL (au moins 2008) inclura le bon index dans le plan.
Si
la source
Cette méthode fonctionne bien pour moi. J'utilise ISNULL () pour le champ de clé primaire et COALESCE () si le champ ne doit pas être la clé primaire, mais doit également avoir une valeur non nullable. Cet exemple génère un champ ID avec une clé primaire non Nullable. Les autres champs ne sont pas des clés et ont (Aucun) comme attribut Nullable.
si vous n'avez vraiment pas de clé primaire, vous pouvez en usurper une en utilisant ROW_NUMBER pour générer une pseudo-clé ignorée par votre code. Par exemple:
la source
NEWID() as id
, mais c'est la même idée. Et il y a des cas d'utilisation légitimes - si vous avez une vue en lecture seule, par exemple. Moche, EF, moche.Le générateur EDM Entity Framework actuel créera une clé composite à partir de tous les champs non nullables de votre vue. Afin de prendre le contrôle de cela, vous devrez modifier la vue et les colonnes de la table sous-jacente en définissant les colonnes sur nullable lorsque vous ne souhaitez pas qu'elles fassent partie de la clé primaire. L'inverse est également vrai, comme je l'ai rencontré, la clé générée par EDM causait des problèmes de duplication de données, j'ai donc dû définir une colonne Nullable comme non Nullable pour forcer la clé composite dans l'EDM à inclure cette colonne.
la source
Context.Entity.ToList()
des enregistrements en double, mais si vous exécutez directement la requête SQL générée par EF (obtenue avec LINQPad), aucune duplication d'enregistrement ne se produit. Semble être un problème de mappage des enregistrements de base de données avec les objets d'entité (POCO) renvoyés, car le PK est déduit à l'aide de la logique expliquée (colonnes non Nullable).Il semble que ce soit un problème connu avec EdmGen: http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/12aaac4d-2be8-44f3-9448-d7c659585945/
la source
Pour obtenir une vue, je ne devais afficher qu'une seule colonne de clé primaire, j'ai créé une deuxième vue qui pointait vers la première et utilisé NULLIF pour rendre les types nullables. Cela a fonctionné pour moi pour faire croire à l'EF qu'il n'y avait qu'une seule clé primaire dans la vue.
Je ne sais pas si cela vous aidera car je ne pense pas que l'EF acceptera une entité sans clé primaire.
la source
Si vous ne voulez pas jouer avec ce que devrait être la clé primaire, je recommande:
ROW_NUMBER
dans votre sélectionla source
En raison des problèmes mentionnés ci-dessus, je préfère les fonctions de valeur de table.
Si vous avez ceci:
créez ceci:
Ensuite, vous importez simplement la fonction plutôt que la vue.
la source