web-dev-qa-db-ja.com

新しいDbContextを呼び出すとき、DbContextOptionsには何が入りますか?

私は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>();
    }
31
Reza

reallyコンテキストを手動で作成したい場合、 configure 次のようにできます:

_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のデフォルトコンストラクターに関するもう1つの注意:EF6では、public ApplicationDbContext(): base("DefaultConnection") {}のように行われました。次に、基本オブジェクトは_System.Configuration.ConfigurationManager_静的クラスを使用して、DefaultConnectionという名前の接続文字列を_web.config_から取得します。新しいAsp.net CoreとEF Coreは可能な限り分離されるように設計されているため、どの構成システムにも依存しないようにする必要があります。代わりに、DbContextOptionsオブジェクトを渡すだけです。そのオブジェクトを作成して構成することは別の問題です。

45
qbik

これは私がそれをする方法です:

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万)に移行していましたが、1つのコンテキストインスタンスがすべてのメモリをすぐに使い果たしてしまいます。したがって、新しいContextインスタンスを作成し、メモリを解放するために特定のしきい値の後に古いインスタンスを破棄する必要がありました。

これはエレガントなソリューションではありませんが、私にとってはうまくいきました。

1
Aven