調用新的DbContext時DbContextOptions會發生什麼?

asp.net-core entity-framework entity-framework-core

我沒有使用DI,只想從我的控制器中調用DbContext。我正在努力弄清楚'選項'應該是什麼?

ApplicationDbContext.cs

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{

    public DbSet<Gig> Gigs { get; set; }
    public DbSet<Genre> Genres { get; set; }


    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        // Customize the ASP.NET Identity model and override the defaults if needed.
        // For example, you can rename the ASP.NET Identity table names and more.
        // Add your customizations after calling base.OnModelCreating(builder);
    }
}

GigsController.cs

    public class GigsController : Controller
{
    private ApplicationDbContext _context;

    public GigsController()
    {
        _context = new ApplicationDbContext();
    }


    public IActionResult Create()
    {
        var viewModel = new GigFormViewModel
        {
            Genres = _context.Genres.ToList()
        };


        return View(viewModel);
    }
}

問題出現在我的GigsController構造函數中:

_context = new ApplicationDbContext();

我錯了,因為我需要將一些東西傳遞給ApplicationDbContext。沒有給出的參數對應於'ApplicationDbContext.ApplicationDbContext(DbContextOptions)'所需的形式參數'options'

我嘗試在從base()派生的ApplicationDbContext中創建一個默認構造函數,但這也不起作用。

在我的startup.cs中,我已經配置了ApplicationDbContext

        public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

        services.AddMvc();

        // Add application services.
        services.AddTransient<IEmailSender, AuthMessageSender>();
        services.AddTransient<ISmsSender, AuthMessageSender>();
    }

一般承認的答案

如果您真的想手動創建上下文,那麼您可以像這樣配置它:

var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
optionsBuilder.UseSqlServer(Configuration.GetConnectionStringSecureValue("DefaultConnection"));
_context = new ApplicationDbContext(optionsBuilder.Options); 

DbContextOptionsBuilder<ApplicationDbContext>類是services.AddDbContext<ApplicationDbContext>(options => )中的options參數的類型。但是在控制器中,您無權訪問Configuration對象,因此您必須將其公開為Startup.cs靜態字段或使用其他一些技巧,這都是不好的做法。

獲取ApplicationDbContext的最佳方法是通過DI獲取它:

public GigsController(ApplicationDbContext context)
{
    _context = context;
}

DI容器將負責實例化和處理 ApplicationDbContext 。請注意,您已在Startup.cs正確配置了所有內容:

services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

這是配置DI,為什麼不使用它呢?

關於DbContext的默認構造函數的DbContext注意DbContext :在DbContext它是這樣完成的: public ApplicationDbContext(): base("DefaultConnection") {} 。然後基礎對象將使用System.Configuration.ConfigurationManager靜態類從web.config獲取名為DefaultConnection的連接字符串。新的Asp.net Core和EF Core旨在盡可能多地解耦,因此它不應該依賴於任何配置系統。相反,您只需傳遞一個DbContextOptions對象 - 創建該對象並對其進行配置是一個單獨的問題。


熱門答案

我就是這樣做的:

public class GigsController : Controller
{
    private readonly IConfiguration _configuration;
    private string _connectionString;
    DbContextOptionsBuilder<ApplicationDbContext> _optionsBuilder;

    public GigsController (IConfiguration configuration)
    {
        _configuration = configuration;
        _optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
        _connectionString = _configuration.GetConnectionString("DefaultConnection");
        _optionsBuilder.UseSqlServer(_connectionString);
    }

    public IActionResult Index()
    {
        using(ApplicationDbContext _context = new ApplicationDbContext(_optionsBuilder.Options))
        {
             // .....Do something here
        }
    }
}

最近我將一個非常大的數據集遷移到數據庫(大約1000萬),一個上下文實例將快速佔用我的所有記憶。因此,我必須創建一個新的Context實例並在特定閾值之後處置舊實例以釋放內存。

這不是一個優雅的解決方案,但對我有用。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因