4.1 Code First Oracle插入PL/SQL代码



我的项目有两个EF 4.1上下文,一个是模型优先,另一个是代码优先。这两个上下文都扩展了DbContext,并且连接到Oracle数据库。

当对一个大表(5M条记录)执行更新时,model-first上下文会像预期的那样生成SQL,并且运行速度很快(毫秒级):

update <schema.table_name> set field = 'value' where id = 1234

当对一个大表(4.7M条记录)执行更新时,code-first上下文会产生一些奇怪的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?

这个问题的答案是双重的。

从生成的SQL中删除PL/SQL

数据库中的列名是全大写的("UWI"),而类上的属性是驼峰大小写的("UWI")。我将属性名称更改为全大写,EF删除了PL/SQL代码,只生成SQL:

UPDATE "SCHEMA"."TABLE"
SET "FIELD" = "VALUE"
WHERE ("UWI" = '2224434')

但是,这并不能提高性能。

为什么Update Was Slow

在与DBA一起跟踪查询之后,我们发现EF将Uwi的值绑定到一个十六进制字符串,而不是"2224434"。这将导致Oracle执行全表扫描,从而影响性能。我需要在Uwi属性上指定列类型,如下所示:

this.Property(entity => entity.Uwi).HasColumnName("UWI").HasColumnType("VARCHAR2");

HasColumnType是神奇子弹,我的更新语句在80毫秒内返回。

最新更新