我正在尝试将Entity Framework 6(EF)与Visual FoxPro数据库一起使用(使用NuGet中的包VFPEntityFrameworkProvider2)我能够很好地建立连接。我能够从大多数表加载数据。
当我尝试检索具有大约240个字段的某种类型的DbSet时,会出现问题。抛出的异常有消息:
此行的已编译代码太长。
最好我明白,EF组成了SQL select语句来检索数据,而且这个语句太长了。当我使用调试器检查局部变量时,我看到一个SQL语句,其长度接近16000个字符,而maximum allowed command length for VFP is 8,192 bytes
我不太清楚如何解决这个问题,因为我对EF很新。我想我可以编辑一些生成的代码,或者编写一些自定义处理程序。也许我可以批量检索字段,然后组合对象。
此外,我相信可以将我的实体分解为类型和子类型;也许如果我这样做,一次只会检索到一部分字段。
有人能以什么方式建议我解决这个限制吗?
添加了备注:
使用其他数据库不是一种选择。我坚持使用FoxPro,以及这个特定的架构。但是,我可以自由地改变我对问题的处理方法。当然,我可以自己编写数据库访问代码,但能够使用EF会非常好。
发送到VFP的查询实际上看起来像这样:
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 :(得分:2)
sql语句可能超过8000+限制的原因有很多。作为VFP EF提供程序的作者,我已经尝试过尽可能地减少sql语句,因为VFP和实体框架之间存在各种约束。但是240个领域的空间不大。就个人而言,我会选择Cetin Basoz的建议,即通过创建表示表的一部分以减少sql语句的多个类来将其视为多个表。或者,您可以使用LINQ Select操作提供字段的子集。这应该减少你的声明,使其不超过8000+限制。
(关闭你的linq语句的假设,因为它没有显示......) 如果您确实需要所有列,那么您可能希望尝试在仅获取主键的查询与使用主键返回所有字段的查询之间分解查询。这可能适合你。
答案 1 :(得分:0)
虽然您可能无法选择数据库,但您是否可以选择实体框架?我发现使用Dapper更适合这种情况,并且可以让您对查询进行低级控制。
答案 2 :(得分:0)
我自己的答案:在使用了一段时间后,我发现表格是以只读方式添加到EDMX模型中的。这意味着它从select语句中进行选择,该语句是冗余的,并且是select语句的大小。当我手动编辑EDMX文件并强制它将表视为读写时,问题就消失了。
此外,根据Tom的建议,我逐渐更加欣赏代码优先方法。我彻底废弃了EDMX模型。我发现这更容易管理,因为我通过模型的类属性控制每个字段的处理方式。使用代码优先,我的上下文类的自定义可能不会被覆盖;这对我来说是完美的,因为我需要自定义构造函数并覆盖SaveChanges和其他方法。