2017-05-09 4 views
0

J'essaie d'utiliser Entity Framework 6 (EF) avec une base de données Visual FoxPro (en utilisant le package VFPEntityFrameworkProvider2 de NuGet) Je suis en mesure de faire la connexion très bien. Je suis capable de charger des données de la plupart des tables..NET - using Entity Framework avec Visual FoxPro - erreur "Le code compilé pour cette ligne est trop long."

Le problème se produit lorsque j'essaie de récupérer un DbSet d'un certain type qui a environ 240 champs. L'exception qui a été lancée contient le message suivant:

Le code compilé pour cette ligne est trop long.

1

mieux que je comprends, EF Compose l'instruction select SQL pour récupérer les données, et cette déclaration est trop long. Comme j'utilise le débogueur pour examiner les variables locales, je vois une instruction SQL, dont la longueur est proche de 16000 caractères, alors que maximum allowed command length for VFP is 8,192 bytes

Je ne suis pas sûr de savoir comment résoudre ce problème, car je suis relativement nouveau pour EF. J'imagine que je pourrais être en mesure d'éditer du code généré, ou peut-être écrire un gestionnaire personnalisé. Peut-être que je pourrais récupérer les champs par lots, puis composer l'objet.

Aussi, je crois qu'il est possible de décomposer mon entité en un type et un sous-type; peut-être que si je le fais, seule une partie des champs sera récupérée à la fois. Est-ce que quelqu'un peut suggérer de quelle manière je pourrais résoudre cette limitation?

notes Ajouté:

Il est pas une option d'utiliser une autre base de données. Je suis coincé avec FoxPro, et ce schéma spécifique. Cependant, je suis libre de changer mon approche du problème. Bien sûr, je peux écrire moi-même le code d'accès à la base de données, mais ce serait très agréable de pouvoir utiliser EF.

La requête envoyée à VFP ressemble en fait quelque chose comme ceci:

SELECT 
E1.Wn_Ref, 
E1.Wn_Surname, 
E1.Wn_Forenam, 
E1.Wn_Dirctr, 
... 
E1.Wn_Chqno, 
CAST(E1.Wn_Lelval AS n(20,2)) AS Wn_Lelval, 
E1.Wn_Dirstpd, 
... 
E1.Wn_Leavdt, 
CAST(E1.Wn_Grsprv AS n(20,2)) AS Wn_Grsprv, 
CAST(E1.Wn_Taxprv AS n(20,2)) AS Wn_Taxprv, 
E1.Wn_Ovride, 
E1.Wn_Nichgpr, 
... 
E1.Wn_Totabs, 
CAST(E1.Wn_Tgrspay AS n(20,2)) AS Wn_Tgrspay, 
CAST(E1.Wn_Tottax AS n(20,2)) AS Wn_Tottax, 
CAST(E1.Wn_Totpens AS n(20,2)) AS Wn_Totpens, 
CAST(E1.Wn_Totsspr AS n(20,2)) AS Wn_Totsspr, 
CAST(E1.Wn_Totsmp AS n(20,2)) AS Wn_Totsmp, 
CAST(E1.Wn_Totchrt AS n(20,2)) AS Wn_Totchrt, 
CAST(E1.Wn_Totcmee AS n(20,2)) AS Wn_Totcmee, 
CAST(E1.Wn_Totcmer AS n(20,2)) AS Wn_Totcmer, 
CAST(E1.Wn_Tcmeeyr AS n(20,2)) AS Wn_Tcmeeyr, 
CAST(E1.Wn_Tcmeryr AS n(20,2)) AS Wn_Tcmeryr, 
CAST(E1.Wn_Totpenl AS n(20,2)) AS Wn_Totpenl, 
CAST(E1.Wn_Totpay AS n(20,2)) AS Wn_Totpay, 
CAST(E1.Wn_Tothol AS n(20,1)) AS Wn_Tothol, 
CAST(E1.Wn_Roundbf AS n(20,2)) AS Wn_Roundbf, 
E1.Wl_Totsspd, 
E1.Wl_Totabs, 
CAST(E1.Wl_Tgrspay AS n(20,2)) AS Wl_Tgrspay, 
CAST(E1.Wl_Tottax AS n(20,2)) AS Wl_Tottax, 
CAST(E1.Wl_Totpens AS n(20,2)) AS Wl_Totpens, 
CAST(E1.Wl_Totsspr AS n(20,2)) AS Wl_Totsspr, 
CAST(E1.Wl_Totsmp AS n(20,2)) AS Wl_Totsmp, 
CAST(E1.Wl_Totchrt AS n(20,2)) AS Wl_Totchrt, 
CAST(E1.Wl_Totcmee AS n(20,2)) AS Wl_Totcmee, 
CAST(E1.Wl_Totcmer AS n(20,2)) AS Wl_Totcmer, 
CAST(E1.Wl_Tcmeeyr AS n(20,2)) AS Wl_Tcmeeyr, 
CAST(E1.Wl_Tcmeryr AS n(20,2)) AS Wl_Tcmeryr, 
CAST(E1.Wl_Totpenl AS n(20,2)) AS Wl_Totpenl, 
CAST(E1.Wl_Totpay AS n(20,2)) AS Wl_Totpay, 
CAST(E1.Wl_Tothol AS n(20,1)) AS Wl_Tothol, 
CAST(E1.Wl_Txb AS n(20,2)) AS Wl_Txb, 
CAST(E1.Wl_Tax AS n(20,2)) AS Wl_Tax, 
CAST(E1.Wl_Net AS n(20,2)) AS Wl_Net, 
CAST(E1.Wl_Erni AS n(20,2)) AS Wl_Erni, 
CAST(E1.Wl_Eeni AS n(20,2)) AS Wl_Eeni, 
CAST(E1.Wl_Cnoni AS n(20,2)) AS Wl_Cnoni, 
CAST(E1.Wl_Nien AS n(20,2)) AS Wl_Nien, 
CAST(E1.Wl_Nieco AS n(20,2)) AS Wl_Nieco, 
CAST(E1.Wl_Compee AS n(20,2)) AS Wl_Compee, 
CAST(E1.Wl_Comper AS n(20,2)) AS Wl_Comper, 
CAST(E1.Wl_Pen AS n(20,2)) AS Wl_Pen, 
CAST(E1.Wl_Penbl AS n(20,2)) AS Wl_Penbl, 
CAST(E1.Wl_Roundcf AS n(20,2)) AS Wl_Roundcf, 
CAST(E1.Wn_Ssp1 AS n(20,2)) AS Wn_Ssp1, 
CAST(E1.Wn_Ssp2 AS n(20,2)) AS Wn_Ssp2, 
CAST(E1.Wn_Ssp3 AS n(20,2)) AS Wn_Ssp3, 
CAST(E1.Wn_Ssp4 AS n(20,2)) AS Wn_Ssp4, 
CAST(E1.Wn_Ssp5 AS n(20,2)) AS Wn_Ssp5, 
CAST(E1.Wn_Ssp6 AS n(20,2)) AS Wn_Ssp6, 
CAST(E1.Wn_Ssp7 AS n(20,2)) AS Wn_Ssp7, 
CAST(E1.Wn_Ssp8 AS n(20,2)) AS Wn_Ssp8, 
E1.Wn_Ssprate, 
... 
E1.Wn_Pwxretn 
FROM (SELECT 
Wname.Wn_Ref, 
... 
Wname.Wn_Chqno, 
CAST(Wname.Wn_Lelval AS n(20,2)) AS Wn_Lelval, 
Wname.Wn_Dirstpd, 
Wname.Wn_Payfrq, 
Wname.Wn_Birth, 
Wname.Wn_Startdt, 
Wname.Wn_Leavdt, 
CAST(Wname.Wn_Grsprv AS n(20,2)) AS Wn_Grsprv, 
CAST(Wname.Wn_Taxprv AS n(20,2)) AS Wn_Taxprv, 
Wname.Wn_Ovride, 
... 
Wname.Wn_Totabs, 
CAST(Wname.Wn_Tgrspay AS n(20,2)) AS Wn_Tgrspay, 
CAST(Wname.Wn_Tottax AS n(20,2)) AS Wn_Tottax, 
CAST(Wname.Wn_Totpens AS n(20,2)) AS Wn_Totpens, 
CAST(Wname.Wn_Totsspr AS n(20,2)) AS Wn_Totsspr, 
CAST(Wname.Wn_Totsmp AS n(20,2)) AS Wn_Totsmp, 
CAST(Wname.Wn_Totchrt AS n(20,2)) AS Wn_Totchrt, 
CAST(Wname.Wn_Totcmee AS n(20,2)) AS Wn_Totcmee, 
CAST(Wname.Wn_Totcmer AS n(20,2)) AS Wn_Totcmer, 
CAST(Wname.Wn_Tcmeeyr AS n(20,2)) AS Wn_Tcmeeyr, 
CAST(Wname.Wn_Tcmeryr AS n(20,2)) AS Wn_Tcmeryr, 
CAST(Wname.Wn_Totpenl AS n(20,2)) AS Wn_Totpenl, 
CAST(Wname.Wn_Totpay AS n(20,2)) AS Wn_Totpay, 
CAST(Wname.Wn_Tothol AS n(20,1)) AS Wn_Tothol, 
CAST(Wname.Wn_Roundbf AS n(20,2)) AS Wn_Roundbf, 
Wname.Wl_Totsspd, 
Wname.Wl_Totabs, 
CAST(Wname.Wl_Tgrspay AS n(20,2)) AS Wl_Tgrspay, 
CAST(Wname.Wl_Tottax AS n(20,2)) AS Wl_Tottax, 
CAST(Wname.Wl_Totpens AS n(20,2)) AS Wl_Totpens, 
CAST(Wname.Wl_Totsspr AS n(20,2)) AS Wl_Totsspr, 
CAST(Wname.Wl_Totsmp AS n(20,2)) AS Wl_Totsmp, 
CAST(Wname.Wl_Totchrt AS n(20,2)) AS Wl_Totchrt, 
CAST(Wname.Wl_Totcmee AS n(20,2)) AS Wl_Totcmee, 
CAST(Wname.Wl_Totcmer AS n(20,2)) AS Wl_Totcmer, 
CAST(Wname.Wl_Tcmeeyr AS n(20,2)) AS Wl_Tcmeeyr, 
CAST(Wname.Wl_Tcmeryr AS n(20,2)) AS Wl_Tcmeryr, 
CAST(Wname.Wl_Totpenl AS n(20,2)) AS Wl_Totpenl, 
CAST(Wname.Wl_Totpay AS n(20,2)) AS Wl_Totpay, 
CAST(Wname.Wl_Tothol AS n(20,1)) AS Wl_Tothol, 
CAST(Wname.Wl_Txb AS n(20,2)) AS Wl_Txb, 
CAST(Wname.Wl_Tax AS n(20,2)) AS Wl_Tax, 
CAST(Wname.Wl_Net AS n(20,2)) AS Wl_Net, 
CAST(Wname.Wl_Erni AS n(20,2)) AS Wl_Erni, 
CAST(Wname.Wl_Eeni AS n(20,2)) AS Wl_Eeni, 
CAST(Wname.Wl_Cnoni AS n(20,2)) AS Wl_Cnoni, 
CAST(Wname.Wl_Nien AS n(20,2)) AS Wl_Nien, 
CAST(Wname.Wl_Nieco AS n(20,2)) AS Wl_Nieco, 
CAST(Wname.Wl_Compee AS n(20,2)) AS Wl_Compee, 
CAST(Wname.Wl_Comper AS n(20,2)) AS Wl_Comper, 
CAST(Wname.Wl_Pen AS n(20,2)) AS Wl_Pen, 
CAST(Wname.Wl_Penbl AS n(20,2)) AS Wl_Penbl, 
CAST(Wname.Wl_Roundcf AS n(20,2)) AS Wl_Roundcf, 
CAST(Wname.Wn_Ssp1 AS n(20,2)) AS Wn_Ssp1, 
CAST(Wname.Wn_Ssp2 AS n(20,2)) AS Wn_Ssp2, 
CAST(Wname.Wn_Ssp3 AS n(20,2)) AS Wn_Ssp3, 
CAST(Wname.Wn_Ssp4 AS n(20,2)) AS Wn_Ssp4, 
CAST(Wname.Wn_Ssp5 AS n(20,2)) AS Wn_Ssp5, 
CAST(Wname.Wn_Ssp6 AS n(20,2)) AS Wn_Ssp6, 
CAST(Wname.Wn_Ssp7 AS n(20,2)) AS Wn_Ssp7, 
CAST(Wname.Wn_Ssp8 AS n(20,2)) AS Wn_Ssp8, 
Wname.Wn_Ssprate, 
... 
FROM Wname Wname) E1 
+0

Apparemment, il s'agit d'une [limitation FoxPro] (https://msdn.microsoft.com/en-us/library/aa976029 (v = vs.71) .aspx) et vous ne seriez pas en mesure d'interroger cela sans EF soit . – GSerg

+0

Remplacer Foxpro avec une autre base de données? –

+0

C'est très souvent pas si simple Robert. Dans beaucoup de cas, les gens ont besoin de parler à une application tierce qui l'utilise, ou c'est leur propre application avec des décennies d'investissement qui ne tourne pas sur six pence à un autre fin. –

Répondre

2

Il existe de nombreuses raisons pour lesquelles l'instruction SQL peut dépasser la limite 8000+. J'ai essayé, en tant qu'auteur de VFP EF Provider, de réduire autant que possible les instructions sql étant donné les diverses contraintes entre VFP et Entity Framework. Mais il n'y a pas beaucoup de marge de manœuvre avec 240 champs. Personnellement, j'irais avec la suggestion de Cetin Basoz de le traiter comme plusieurs tables en créant plusieurs classes qui représentent une partie de la table pour réduire l'instruction sql. Vous pouvez également fournir un sous-ensemble des champs en utilisant l'opération LINQ Select. Cela devrait réduire la déclaration pour vous afin qu'il ne dépasse pas la limite de 8000+. (En quittant les suppositions de votre instruction linq puisqu'elle n'est pas montrée ...) Si vous avez vraiment besoin de toutes les colonnes, vous pouvez essayer de diviser la requête entre une requête qui obtient juste la clé primaire et une requête qui utilise la clé primaire pour retourner tous les champs. Cela pourrait fonctionner pour vous.

+0

Bonjour Tom, merci beaucoup pour votre réponse et les conseils. Une question sans rapport avec vous: la licence de votre composant permet-elle de l'utiliser pour des projets commerciaux? – onTy

+0

Oui, le fournisseur peut être utilisé dans des projets commerciaux. –

+0

Cela fonctionne très bien en utilisant LINQ. Merci pour l'idée. – onTy

0

Même si vous avez pas le choix de la base de données, vous avez le choix avec Entity Framework? Je trouve que l'utilisation de Dapper est un meilleur ajustement dans ce scénario et vous donner un contrôle de bas niveau sur la requête.

+0

Merci pour l'idée. Je vais chercher si elle peut être utilisée comme une solution pour notre projet. – onTy

0

Ma propre réponse: Après avoir travaillé avec cela pendant un moment, j'ai trouvé que les tables ont été ajoutées au modèle EDMX en lecture seule.Cela signifie qu'il sélectionnait à partir d'une instruction select, qui est redondante, et gonflait la taille de l'instruction select. Lorsque j'ai édité manuellement le fichier EDMX et l'ai forcé à traiter la table en lecture-écriture, le problème a disparu.

En outre, sur les conseils de Tom, j'ai commencé à mieux apprécier l'approche du code. J'ai complètement supprimé le modèle EDMX. Je trouve cela beaucoup plus facile à gérer puisque je contrôle comment chaque champ est traité via des attributs sur les propriétés de classe du modèle. En utilisant le code d'abord, il n'y a aucune chance que mes personnalisations aux classes de contexte soient écrasées; C'est parfait pour moi car j'ai besoin de personnaliser les constructeurs et de surcharger SaveChanges et d'autres méthodes.