我正在构建一个ASP.NET MVC 5应用程序,以便一次获得2到12行的只读访问权限。这些记录存储在Oracle 11中,并通过实体框架6从Oracle中的视图进行访问。正如标题所说,使用硬编码值很快,但字符串参数很慢(例如下面的例子) 这很快就会出现:
public List<VW_COLLISIONS_TS> GetCollisions(string collisionMRN)
{
var collisions = (from c in TSP_Context.VW_COLLISIONS_TS
where c.COLLISION_MASTER_RECORD_NUMBER.Equals("902770479")
select c).AsNoTracking();
return collisions.ToList();
}
但这很慢:
public List<VW_COLLISIONS_TS> GetCollisions(string collisionMRN)
{
var collisions = (from c in TSP_Context.VW_COLLISIONS_TS
where .COLLISION_MASTER_RECORD_NUMBER.Equals(collisionMRN)
select c).AsNoTracking();
return collisions.ToList();
}
使用参数大约需要30秒才能返回记录。这是为什么?
更新:我设置了跟踪,这是我得到的:
[#1 - with hard-coded string value]
Opened connection at 2/9/2017 9:48:29 AM -05:00
SELECT
"Extent1"."PERSON_MASTER_RECORD_NUMBER" AS "PERSON_MASTER_RECORD_NUMBER",
"Extent1"."VEHICLE_MODEL" AS "VEHICLE_MODEL",
"Extent1"."PERSON_AGE" AS "PERSON_AGE"
FROM "DWOBDEV"."VW_COLLISIONS_TS" "Extent1"
WHERE ('902770479' = "Extent1"."COLLISION_MASTER_RECORD_NUMBER")
-- Executing at 2/9/2017 9:48:29 AM -05:00
-- Completed in 5 ms with result: OracleDataReader
Closed connection at 2/9/2017 9:44:29 AM -05:00
[2. With string parameter]
Opened connection at 2/9/2017 9:44:17 AM -05:00
SELECT
"Extent1"."PERSON_MASTER_RECORD_NUMBER" AS "PERSON_MASTER_RECORD_NUMBER",
"Extent1"."VEHICLE_MODEL" AS "VEHICLE_MODEL",
"Extent1"."PERSON_AGE" AS "PERSON_AGE"
FROM "DWOBDEV"."VW_COLLISIONS_TS" "Extent1"
WHERE (("Extent1"."COLLISION_MASTER_RECORD_NUMBER" = :p__linq__0) OR (("Extent1"."COLLISION_MASTER_RECORD_NUMBER" IS NULL) AND (:p__linq__0 IS NULL)))
-- p__linq__0: '902770479' (Type = Object)
-- Executing at 2/9/2017 9:44:17 AM -05:00
-- Completed in 12364 ms with result: OracleDataReader
Closed connection at 2/9/2017 9:48:29 AM -05:00
我的同事接受:“我认为当你硬编码时它被视为数字/整数,当你使用字符串时,它将作为varchar / text处理,然后查找空值。尝试使用COLLISION_MASTER_RECORD_NUMBER作为整数变量,如果COLLISION_MASTER_RECORD_NUMBER是数字/ int数据类型。“
你们有什么想法? [注意:目前,COLLISION_MASTER_RECORD_NUMBER是Oracle数据库中的varchar2'号码'(无alpha)]
更新(已回答!): 从Alexander V发布的内容(包括EF链接),我想出了这个:
var collisions = (from c in TSP_Context.VW_COLLISIONS_TS
where c.COLLISION_MASTER_RECORD_NUMBER == (DbFunctions.AsNonUnicode(collisionMRN))
select c).AsNoTracking();
我在Context构造函数中添加了这个:
this.Configuration.UseDatabaseNullSemantics = true;
效果很好。
答案 0 :(得分:0)
您需要检查两种情况下sql查询生成的内容。
尝试在.ToList()调用之前添加:
var sql = ((System.Data.Entity.Core.Objects.ObjectQuery)collisions)
.ToTraceString();
如果你可以发回sql查询,我们会看到这里发生了什么。
UPDATE:(基于@R.Jo发布的sql查询更新)
我认为第二个查询中的性能问题与额外的NULL检查有关:
因此,请尝试使用== "something"
代替.Equals("something")
因为Equals可以为可空类型生成额外的空值检查;
当你做Equals时我们EF需要在这里使用2种不同的数据类型,我们也希望避免这种情况。 (见下面的例子)。
如果示例中的代码不起作用,试试这个'
UseDatabaseNullSemantics = true;
也许有帮助。
(点击此处Why is EF generating SQL queries with unnecessary null-checks?了解更多信息。
修改强>
如果COLLISION_MASTER_RECORD_NUMBER,那么我们可以做类似
的事情public List<VW_COLLISIONS_TS> GetCollisions(string collisionMRN)
{
int collision = int.Parse(collisionMRN);
var collisions = (from c in TSP_Context.VW_COLLISIONS_TS
where .COLLISION_MASTER_RECORD_NUMBER == collision
select c).AsNoTracking();
return collisions.ToList();
}
请告诉我它是否适合您。