【问题标题】:DbContextOptionsBuilder<someType> does not contain a definition for UseSqlServer()DbContextOptionsBuilder<someType> 不包含 UseSqlServer() 的定义
【发布时间】:2021-08-03 20:33:59
【问题描述】:

我在这里查看了几个类似的问题,但到目前为止没有任何帮助。

我正在尝试基于直到运行时才知道的类型动态创建 DbContext。 DbContext 在我的应用程序中引用的另一个库中。我需要将 DbContextOptions 对象传递给 DbContext 的构造函数。所以我正在创建一个 DbContextOptionsBuilder 并尝试调用传递连接字符串的 UseSqlServer() 方法。但是我得到标题中的错误。

其他类似的问题总是说要添加包 Microsoft.EntityFrameworkCore 和 Microsoft.EntityFrameworkCore.SqlServer,我已经这样做了,但没有成功。

这是我现在的代码:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.SqlServer;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

private DbContext GetDbContext()
{
    Console.WriteLine("\nGetting DB Context...");

    Assembly LaytonDBSets = Assembly.Load("LaytonDBSets.Core");

    List<TypeInfo> dbContexts = LaytonDBSets.DefinedTypes.Where(t => typeof(DbContext).IsAssignableFrom(t)).ToList();

    foreach (TypeInfo ti in dbContexts)
    {
        Type ctxType = LaytonDBSets.GetType(ti.FullName);

        // Get the DbContextOptions to pass to the DbContext constructor
        Type dbContextOptionsBuilderBase = typeof(DbContextOptionsBuilder<>);
        Type dbContextOptionsBuilderType = dbContextOptionsBuilderBase.MakeGenericType(ctxType);
        dynamic dbContextOptionsBuilder = Activator.CreateInstance(dbContextOptionsBuilderType);
        string connStr = iconfig.GetConnectionString(ti.Name);
        dbContextOptionsBuilder.UseSqlServer(connStr); // ERROR HERE
        var options = dbContextOptionsBuilder.Options;

        dynamic ctx = Activator.CreateInstance(ctxType, args: new object[] { options });

        // stuff to be added...
    }

    // stuff to be added...
}

如果有更好的方法来做我正在尝试的事情,请告诉我,我以前从未做过这样的事情。

【问题讨论】:

  • 我的猜测是扩展方法不会绑定到 dynamic dbContextOptionsBuilder 实例,因为它不知道要绑定到它的类型信息才能调用 UseSqlServer()方法。
  • @MartinCostello 我可能是错的,但这是我收到的错误消息:“Microsoft.EntityFrameworkCore.DbContextOptionsBuilder'不包含'UseSqlServer'的定义”;这是否意味着它确实知道它试图绑定的类型?

标签: c# reflection entity-framework-core


【解决方案1】:

这是执行此操作的辅助类:

public class ContextHelper
{
    public static DbContext CreateDbContext<T>(string connectionString) where T : DbContext
    {
        var optionsBuilder = new DbContextOptionsBuilder<T>();
        optionsBuilder.UseSqlServer(connectionString);

        var options = optionsBuilder.Options;
        var context = (DbContext)Activator.CreateInstance(typeof(T), options);

        return context;
    }

    private static MethodInfo _createDbContext = typeof(ContextHelper).GetMethod("CreateDbContext", new Type[]{typeof(string)});

    public static List<DbContext> CreateDbContexts(IEnumerable<(Type Type, string ConnectionString)> contextTypes)
    {
        var result = new List<DbContext>();
        foreach (var contextType in contextTypes)
        {
            result.Add((DbContext)_createDbContext.MakeGenericMethod(contextType.Type)
                .Invoke(null, new[] {contextType.ConnectionString}));
        }

        return result;
    }
}

在您的情况下的用法:

var typeWithConnectionString = 
    dbContexts.Select(ti => (LaytonDBSets.GetType(ti.FullName), iconfig.GetConnectionString(ti.Name)));

var contexts = ContextHelper.CreateDbContexts(typeWithConnectionString);

【讨论】:

  • 非常感谢!这太棒了!
  • 注意,最好缓存 DbContextOptions,否则 LINQ 查询永远不会命中缓存。
猜你喜欢
  • 2017-11-25
  • 2017-03-13
  • 2021-12-17
  • 2017-08-05
  • 1970-01-01
  • 2020-06-17
  • 2017-08-23
  • 1970-01-01
相关资源
最近更新 更多