如何在单独的类库.net core 中使用 DbContext?
Posted
技术标签:
【中文标题】如何在单独的类库.net core 中使用 DbContext?【英文标题】:How to use DbContext in separate class library .net core? 【发布时间】:2020-05-02 07:50:20 【问题描述】:我正在尝试从类库中的 .net core 3.1 MVC 项目访问我的 dbcontext。目前我将我的数据库注入到startup.cs
的服务集合中
public class AppDbContext : DbContext
public DbSet<User> Users get; set;
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
protected override void OnModelCreating(ModelBuilder builder)
// Handles duplicate entry for email in user table
builder.Entity<User>()
.HasIndex(u => u.Email)
.IsUnique();
但是,我不确定如何在我的类库中访问这个 AppDbContext。我尝试像访问控制器一样访问它,但显然它不知道 DI 容器。
更多信息: 此库用于发出的常见请求。它必须始终与主 Web 应用程序分开,并且用户永远不必在此类库中编写代码。因此,我需要能够从类库中访问主 Web 项目中的 dbcontext。
【问题讨论】:
AppDbContext 类是在哪里创建的? 在主应用程序中。 你知道如何为不是 DbContext 的类做这件事吗? DbContext 是否有特定的东西阻止你的类库访问它,或者这是一个普遍的依赖问题? 我通常做的是将数据上下文移动到它自己的库中并从那里重用。 @TheDizzle 请检查我的答案。希望对您有所帮助。 【参考方案1】:正如您所说,您正在开发类库以使用库客户端传递的任何DbContext
,那么您必须执行以下操作:
首先考虑你的类库有以下接口和类,你的DbContext
将被使用:
public interface IUnitOfWork
IRepository<T> Repository<T>() where T : class;
Task SaveChangesAsync();
internal class UnitOfWork : IUnitOfWork
private readonly DbContext _dbContext;
private Hashtable _repositories;
public UnitOfWork(DbContext dbContext)
_dbContext = dbContext;
public IRepository<T> Repository<T>() where T : class
if (_repositories == null)
_repositories = new Hashtable();
var type = typeof(T).Name;
if (!_repositories.ContainsKey(type))
var repositoryType = typeof(Repository<>);
var repositoryInstance =
Activator.CreateInstance(repositoryType.MakeGenericType(typeof(T)), _dbContext);
_repositories.Add(type, repositoryInstance);
return (IRepository<T>)_repositories[type];
public async Task SaveChangesAsync()
await _dbContext.SaveChangesAsync();
public interface IRepository<TEntity> where TEntity : class
Task InsertEntityAsync(TEntity entity);
internal class Repository<TEntity> : IRepository<TEntity> where TEntity : class
private readonly DbContext _dbContext;
public Repository(DbContext dbContext)
_dbContext = dbContext;
public async Task InsertEntityAsync(TEntity entity)
await _dbContext.Set<TEntity>().AddAsync(entity);
现在在你的类库中编写一个服务集合扩展方法如下:
public static class ServiceCollectionExtensions
public static void RegisterYourLibrary(this IServiceCollection services, DbContext dbContext)
if (dbContext == null)
throw new ArgumentNullException(nameof(dbContext));
services.AddScoped<IUnitOfWork, UnitOfWork>(uow => new UnitOfWork(dbContext));
现在在您的客户端应用程序的Startup.ConfigureServices
中如下:
public void ConfigureServices(IServiceCollection services)
string connectionString = Configuration.GetConnectionString("ConnectionStringName");
services.AddDbContext<AppDbContext>(option => option.UseSqlServer(connectionString));
ServiceProvider serviceProvider = services.BuildServiceProvider();
AppDbContext appDbContext = serviceProvider.GetService<AppDbContext>();
services.RegisterYourLibrary(appDbContext); // <-- Here passing the DbConext instance to the class library
.......
用法:
public class EmployeeController : Controller
private readonly IUnitOfWork _unitOfWork;
public EmployeeController(IUnitOfWork unitOfWork)
_unitOfWork = unitOfWork;
public async Task<IActionResult> Insert()
Employee employee = new Employee();
await _unitOfWork.Repository<Employee>().InsertEntityAsync(employee);
await _unitOfWork.SaveChangesAsync();
return View();
【讨论】:
我通过了dbContext,但它不知道设置的任何模型。 谢谢你。我能够添加到这个工作解决方案中:-------- interface IRepository在收到 PMC 命令Add-Migration InitialCreate
的错误后,我就这样解决了:
Unable to create an object of type 'ApplicationDbContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
将IDesignTimeDbContextFactory
添加为@JoseGonzalez
,但我不想在IDesignTimeDbContextFactory
的实现中硬编码我的连接字符串,而是从我的应用程序appsettings.json
中获取它。
最终解决方案如下所示:
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace MyNamespace
public class ApplicationDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext>
public ApplicationDbContext CreateDbContext(string[] args)
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var optionsBuilder = new DbContextOptionsBuilder();
var connectionString = configuration
.GetConnectionString("DefaultConnection");
optionsBuilder.UseSqlServer(connectionString);
return new ApplicationDbContext(optionsBuilder.Options);
然后我可以像这样在我的其他项目中使用它:
var applicationDbContextFactory = new ApplicationDbContextFactory();
using (var dbContext = applicationDbContextFactory.CreateDbContext(args))
【讨论】:
【参考方案3】:如果您在另一个项目/lib 中创建了 dbcontext,您首先需要迁移它,然后更新它。 EF 使用 IDesignTimeDbContextFactory 通知有关该库的实体框架。
public class ContextFactoryNeededForMigrations : IDesignTimeDbContextFactory<AppDbContext >
private const string ConnectionString =
"Server=(localdb)\\mssqllocaldb;Database=EfCoreInActionDb;Trusted_Connection=True;MultipleActiveResultSets=true";
public EfCoreContext CreateDbContext(string[] args)
var optionsBuilder = new DbContextOptionsBuilder<EfCoreContext>();
optionsBuilder.UseSqlServer(ConnectionString,
b => b.MigrationsAssembly("DataLayer"));
return new EfCoreContext(optionsBuilder.Options);
然后你可以像这样将它添加到你的 startup.cs DI 容器中。
services.AddDbContextPool<AppDbContext >(
options => options.UseSqlServer(connection,
b => b.MigrationsAssembly("DataLayer")));
这是关于这个主题的好教程。 enter link description here
【讨论】:
以上是关于如何在单独的类库.net core 中使用 DbContext?的主要内容,如果未能解决你的问题,请参考以下文章
Visual Studio - 创建面向 .Net Core 的类库
.net core中加载lua脚本的类库: MoonSharp