簡體   English   中英

如何在單獨的類庫 .net core 中使用 DbContext?

[英]How to use DbContext in separate class library .net core?

我正在嘗試從類庫中的 .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。

正如您所說,您正在開發類庫以使用庫客戶端傳遞的任何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();
    }
}

從 PMC 命令Add-Migration InitialCreate得到錯誤后,我解決了這個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))
{
    
}

如果您在另一個項目/庫中創建了 dbcontext,您首先需要遷移它,並更新它。 EF 使用 IDesignTimeDbContextFactory 通知有關 lib 的實體框架。

 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"))); 

這是關於這個主題的很好的教程。 在此處輸入鏈接描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM