3

我知道我可能有点厚,但是......

首先使用 EF 代码创建了一个新的 MVC3 测试应用程序。

语境:

    public class EmployeeContext : DbContext
    {
        public DbSet<Employee> Employees { get; set; }
    }

控制器:

    public ActionResult Index()
    {
        List<Employee> employees;
        using (var ctx = new EmployeeContext())
        {
            employees = ctx.Employees.ToList();
        }
        return View(employees);
    }

    [HttpPost]
    public ActionResult Create(Employee employee)
    {
        using (var ctx = new EmployeeContext())
        {
            ctx.Employees.Add(employee);
            ctx.SaveChanges();
        }

        return RedirectToAction("Index");
    }

正如预期的那样,EF 创建了数据库,我可以创建并列出一个员工。

现在为 miniprofiler。

从 nuget 添加了 miniprofiler.EF 1.9.1。

我只需要将以下行添加到 global.asax application_start 方法:

    MiniProfilerEF.Initialize();

当我使用它运行时,我得到一个“无法确定'System.Data.SqlClient.SqlConnection'类型的连接的提供程序名称。” 例外。

我不必在 web.config 中添加任何内容,对吗?

4

3 回答 3

1

不,你不厚:-)。EF 和 MiniProfiler.EF 1.9.1 似乎存在问题。看到这个问题。显然,在 2.0 版中会有一个解决方法。

于 2011-10-13T13:50:51.067 回答
0

有一个当前未解决的问题打开跟踪此:

http://code.google.com/p/mvc-mini-profiler/issues/detail?id=112&q=Unable%20to%20determine%20the%20provider%20name

于 2011-12-14T01:14:18.733 回答
0

问题:

如果在我们的 Entity Framework 数据库初始化策略执行之前初始化 MiniProfiler,则初始化会失败,并出现有关缺少迁移表的错误。

如果首先执行 Entity Framework 数据库初始化策略,则对实体的访问将失败并出现类型转换异常,因为 MiniProfiler DbConnection 被尝试强制进入 SqlConnection 变量(在内部泛型中)。

原因:

当 MiniProfiler 初始化时,它使用反射从 System.Data.Common.DbProviderFactories 中的私有静态字段中检索数据库提供程序的集合。然后,它使用 MiniProfiler shim 提供程序重写此列表以替换本机提供程序。这允许 MiniProfiler 以静默方式拦截对数据库的任何调用。

当实体框架初始化时,它开始编译数据模型并创建缓存的初始化数据库,存储在一些私有静态字段内的 System.Data.Entity.Internal.LazyInternalContext 中。创建这些后,针对 DbContext 的查询将使用缓存的模型和数据库,这些模型和数据库在内部键入以使用初始化时存在的提供程序。

当 Entity Framework 数据库初始化策略运行时,它需要访问裸机的原生 Sql 提供程序,而不是 MiniProfiler shim,以便正确生成 SQL 以创建表。但是一旦对原生提供者进行了这些调用,原生提供者就会被缓存到 LazyInternalContext 中,并且我们不能再注入 MiniProfiler shims 而不会出现运行时故障。

我的解决方案:

访问 System.Data.Entity.Internal.LazyInternalContext 中的私有集合并清除缓存的编译模型和初始化的数据库。

如果我在 EF 数据库初始化策略的操作和 MiniProfiler 的初始化之间执行此清除,则可以插入 MiniProfiler 垫片,而不会导致以后的运行时失败。

代码: 这段代码对我有用:

Type type = typeof(DbContext).Assembly.GetType("System.Data.Entity.Internal.LazyInternalContext");
object concurrentDictionary = (type.GetField("InitializedDatabases", BindingFlags.NonPublic | BindingFlags.Static)).GetValue(null);
var initializedDatabaseCache = (IDictionary)concurrentDictionary;
if (initializedDatabaseCache != null) initializedDatabaseCache.Clear();
object concurrentDictionary2 = (type.GetField("CachedModels", BindingFlags.NonPublic | BindingFlags.Static)).GetValue(null);
var modelsCache = (IDictionary)concurrentDictionary2;
if (modelsCache != null) modelsCache.Clear();

警告:

LazyInternalContext 中内部字段的名称似乎在 EF 版本之间发生变化,因此您可能需要修改此代码以使用您在项目中包含的确切版本的 EF。

于 2013-04-18T17:19:08.670 回答