新しい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'に対応する引数はありません

私はApplicationDbContextのbase()から派生したデフォルトのコンストラクタを作成しようとしましたが、どちらもうまくいきませんでした。

私の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インスタンス化と破棄を行いApplicationDbContextStartup.csすべて正しく設定されていることに注意してください。

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

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

それがDIの設定です。

DbContextのデフォルトコンストラクタに関するもう1つの注意: DbContextでは、次のように行われていました。public 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万)、そして1つのコンテキストインスタンスが私の記憶をすべて使い果たします。そのため、新しいContextインスタンスを作成し、メモリを解放するために特定のしきい値の後に古いContextインスタンスを破棄する必要がありました。

これは優雅な解決策ではありませんが、私のために働きました。



Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ