我的项目有两个EF 4.1上下文,一个是模型优先,另一个是代码优先。这两个上下文都扩展了DbContext并连接到Oracle数据库。
当执行对大表(5M记录)的更新时,模型优先上下文会产生预期的SQL,并且它会快速运行(毫秒):
update <schema.table_name> set field = 'value' where id = 1234
当执行对大表(4.7M记录)的更新时,代码优先上下文会产生一些奇怪的PL / SQL:
declare
"UWI" nvarchar2(
128)
;
begin
update
"SCHEMA"."TABLE"
set "FIELD" = 'VALUE' /* :p0 */,
where ("UWI" = '2224434' /* :p37 */)
returning
"UWI" into
"UWI";
open '' /* :p38 */ for select
"UWI" as "UWI"
from dual;
end;
此更新语句需要3秒钟才能完成。
以下是代码优先上下文的代码优先的EntityTypeConfiguration:
public WellEntityConfiguration()
{
this.ToTable("TABLE", "SCHEMA");
this.HasKey(entity => entity.Uwi);
this.Property(entity => entity.Uwi).HasColumnName("UWI");
... //lots of properties being set
}
我可以设置一个配置来强制EF生成简单的更新语句而不是疯狂的PL / SQL吗?
答案 0 :(得分:1)
答案是双重的。
从生成的SQL中删除PL / SQL
数据库中的列名是all-caps(“UWI”),而类上的属性是camel-case(“Uwi”)。我将属性名称更改为all-caps,EF删除PL / SQL代码并仅生成SQL:
UPDATE "SCHEMA"."TABLE"
SET "FIELD" = "VALUE"
WHERE ("UWI" = '2224434')
但是,这并没有提高性能。
更新为何缓慢
在使用DBA跟踪查询后,我们发现EF将Uwi的值绑定到十六进制字符串而不是“2224434”。这导致Oracle进行全表扫描并影响性能。我需要在Uwi
属性上指定列类型,如下所示:
this.Property(entity => entity.Uwi).HasColumnName("UWI").HasColumnType("VARCHAR2");
HasColumnType
是神奇的子弹,我的更新语句在80毫秒内返回。