我已经尝试过这些实体检索方法:
通用,Single
:~0.05
var obj = MyDbContext.Set<Person>().Single(p => p.Id == 2);
通用,Find
:~4s
var obj = MyDbContext.Set<Person>().Find(2);
非通用,Find
:~4s
var obj = (Person)MyDbContext.Set(typeof(Person)).Find(2);
我无法弄清楚,为什么时间如此不同?
我读过这个老问题:DbSet.Find method ridiculously slow compared to .SingleOrDefault on ID
这不是我的问题,因为我有
MyDbContext.Configuration.AutoDetectChangesEnabled = false;
虽然它是MyDbContext
实例上的第一个查询,但在这些测量之前,我正在做很多工作,并且缓存可以以某种方式相关。
所有三种方法的第二次和下一次调用都很快。
问题是我不能使用泛型方法,因为我在运行时收到了set类型。
答案 0 :(得分:1)
我遇到了与EDMX模型类似的问题。第一个查询非常慢。我通过在创建DbContext时缓存MetadataWorkspace解决了我的问题:
private static readonly Lazy<MetadataWorkspace> EntitiesMetadataWorkspace;
static MyWrapper()
{
EntitiesMetadataWorkspace = new Lazy<MetadataWorkspace>(() => new MetadataWorkspace(CommonDbConfiguration.ModelMetadataArray, new[] { CommonDbConfiguration.ModelAssembly }), LazyThreadSafetyMode.ExecutionAndPublication);
}
public MyWrapper(OracleConnection oracleConnection)
{
this.entities = new Lazy<Entities>(() => new Entities(new EntityConnection(EntitiesMetadataWorkspace.Value, oracleConnection, false), false));
}
*实体 - 我的DbContext类。
答案 1 :(得分:-1)
Find vs Single不能相同,因为Find首先检查内存是否存在所需的实体,如果它没有被跟踪并且存在于内存中,则EF通过生成sql查询(如single)来从数据库中请求实体。 此外,您还需要为上下文添加启动时间,这取决于您的上下文的胖度,以及这是否是第一次调用将导致创建数据库。
修改强>
我还想在这里提一下,因为EF6是由nuget(在.NET之外)分发的,运行的机器将在你的应用程序运行时使用JIT编译,这样你的处理器就能理解代码,.NET有一个原生图像生成工具名为“ngen”,它是什么让您将程序集编译为本机图像,该图像使用特定于处理器的代码并将其存储在本机图像缓存中,以便您的应用程序使用该缓存图像代替每次运行你的应用程序时都可以使用它。
因此,您可以使用ngen通过可在VS 2012/2013命令行中运行的此命令加速启动:
ngen install entityframework.dll
希望这有帮助。