实体框架的绩效

时间:2016-01-20 11:16:06

标签: c# performance entity-framework

我还有一个关于EF性能的问题。

有一种方法可以从上下文中获取对象:

tDocumentTyp DocumentTypObject = Context.tDocumentTyps.Where(s => s.DocumentTypID == iTypID).FirstOrDefault();

此方法需要约2979毫秒。

然后我写了一个通过反射获取DBSet的方法,并以这种方式执行:

tDocumentTyp DocumentTypObject = Context.GetEntries<tDocumentTyp>().Where(s => s.DocumentTypID == iTypID).FirstOrDefault();

我的方法需要~222 ms才能执行。

所以现在我的问题是,为什么我的方法比原始方法快得多?或者我的方法有什么问题吗?

为了使这更容易,这是我通过反射获取DBSet的方法:

public static IEnumerable<T> GetEntries<T>(this AppContext DataContext,
    string PropertyName = null, IEnumerable<string> includes = null) where T : IEntity
{
    Type ContextType = typeof(AppContext);
    PropertyInfo Entity = null;
    if (null == PropertyName)
        Entity = ContextType.GetProperty(typeof(T).Name) 
                    ?? ContextType.GetProperty(typeof(T).Name + "s");
    else
        Entity = ContextType.GetProperty(PropertyName);

    if (null == Entity)
        throw new Exception("Could not find the property. If the property is not equal to the tablesname, you have to parametrize it.");
    DbQuery<T> set = ((DbSet<T>)Entity.GetValue(DataContext, null));
    if (includes != null)
        includes.ForEach(f => set = set.Include(f));
    return set;
}

1 个答案:

答案 0 :(得分:0)

第二个例子是获取整个表并在内存中应用Where。您正在应用对System.Linq.Enumerable.Where进行操作的扩展方法IEnumerable<T>。请注意,这是一个内存中实现。在第一个示例中,您使用了对System.Linq.Queryable.Where进行操作的扩展方法IQueryable<T>。这是一种不同的方法,尽管它们具有相同的名称。

如果仔细检查,您还会发现在第一个示例中,method参数的类型为Expression<Func<T, bool>>,而在第二个示例中,它只是Func<T, bool>。这是一个非常重要的区别:可以处理表达式以生成SQL查询。

那么为什么第二个更快呢?好吧,如果没有关于数据源的更多信息,很难回答。但正如其他人在评论中指出的那样,如果数据库没有编入索引,那么选择整个表并在内存中执行过滤器可能比让SQL服务器应用过滤更快。