我正在使用实体框架 4.3.1 代码优先。
我有一个非常简单的表达式和实体模型。
using (var PMCtx = new PMContext("PMEntities"))
{
var results =
PMCtx.Fetch<vwSDHOriginalMW>()
.Where(x => x.DT >= StartDate && x.DT < EndDate)
.ToList();
return results;
}
public class vwSDHOriginalMW : IEntityObject, IPMContext
{
public int Schedule { get; set; }
public DateTime DT { get; set; }
public int HE { get; set; }
public Decimal OrgMW { get; set; }
public Decimal DELIVERMW { get; set; }
public string NERCCode { get; set; }
public string NERCCodeStatus { get; set; }
public int SDHSDHID { get; set; }
}
每次都需要 15 秒,而不仅仅是第一次。该模型映射到 Sql Server 2008 数据库中的视图。我输出了 EF 发送的查询,并在 SSMS 中运行它,只花了几分之一秒。
为什么在实体框架中这么慢?
IEntityObject 似乎是一个标记接口,因此原始程序员可以确定这些是唯一放入泛型的。
EDIT 1 Fetch 最终通过一些层包装器到达它执行此操作的数据层:
private DbSet<TEntity> FetchSet<TEntity>()
where TEntity : class, IEntityObject
{
Type PassedType = typeof(TEntity);
if (!CheckedTypes.Any(x => x.FullName == PassedType.FullName))
if (!PassedType.GetInterfaces().Any(x => CtxInterfaces.Contains(x)))
throw new ArgumentException("Type passed is not a DbSet type of constructed context.");
else
CheckedTypes.Add(PassedType);
return privateContext.Set<TEntity>();
}
EF 正在发送的查询的清理示例
SELECT [Schedule],
[DT],
[HE],
[OrgMW],
[DELIVERMW],
[NERCCode],
[NERCCodeStatus],
[SDHSDHID],
[ScheduleDeliveryHourHistoryID]
FROM [vwSDHOriginalMW]
WHERE ([DT] >= '2/17/2013') AND ([DT] < '2/21/2013')
编辑 2 数据库中的视图实际上比我的实体模型的属性多一列。我将属性添加到模型中。
public class vwSDHOriginalMW : IEntityObject, IPMContext
{
public int Schedule { get; set; }
public DateTime DT { get; set; }
public int HE { get; set; }
public Decimal OrgMW { get; set; }
public Decimal DELIVERMW { get; set; }
public string NERCCode { get; set; }
public string NERCCodeStatus { get; set; }
public int SDHSDHID { get; set; }
//missing property
public int ScheduleDeliveryHourHistoryID { get; set; }
}
昨天加了属性后,有一阵子加速非常快,跑了4秒而不是15秒。但是今天又变慢了,什么都没变。
更新:我进一步缩小了范围。我可以使用两种方法,最终使用相同的 FetchSet。我正在使用的返回一个 IQueryable 而不是 IEnumerable。这看起来很正常,而且因为我是在之后过滤的,所以这是最可取的。但是,返回 IQueryable 的方法需要 15 秒,而 IEnumerable 需要不到一秒。(我在两者上都调用 ToList()) FetchAll 原来只是一个调用 Fetch 并返回 IEnumerable 而不是 IQueryable 的包装器
public IQueryable<TEntity> Fetch<TEntity>() where TEntity : class, Common.IEntityObject
{
return privateContext.Fetch<TEntity>();
}
public IEnumerable<TEntity> FetchAll<TEntity>() where TEntity : class, Common.IEntityObject
{
return privateContext.FetchAll<TEntity>();
}
如果我改变
IEnumerable<vwSDHOriginalMW> results =
PMCtx.Fetch<vwSDHOriginalMW>()
.Where(x => x.DT >= StartDate && x.DT < EndDate)
.ToList();
到
IEnumerable<vwSDHOriginalMW> results =
PMCtx.Fetch<vwSDHOriginalMW>()
.ToList()
.Where(x => x.DT >= StartDate && x.DT < EndDate);
它很快。但这是不可接受的,因为我似乎希望将 where 子句传递给数据库。在这种情况下,在开发环境中,视图只有 180 行,但它有可能达到数百万行,所以我绝对不想在过滤它们之前将所有结果返回到内存中。