官网链接:
Configuring a DbContext
https://docs.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext
Design-time DbContext Creation
https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dbcontext-creation
EF Core design-time tools such as migrations need to be able to discover and create a working instance of a DbContext
type in order to gather details about the application's entity types and how they map to a database schema.
DbContext
must have an instance of DbContextOptions
in order to perform any work. The DbContextOptions
instance carries configuration information such as:
- The database provider to use, typically selected by invoking a method such as
UseSqlServer
orUseSqlite
. These extension methods require the corresponding provider package, such asMicrosoft.EntityFrameworkCore.SqlServer
orMicrosoft.EntityFrameworkCore.Sqlite
. The methods are defined in theMicrosoft.EntityFrameworkCore
namespace. - Any necessary connection string or identifier of the database instance, typically passed as an argument to the provider selection method mentioned above
- Any provider-level optional behavior selectors, typically also chained inside the call to the provider selection method
- Any general EF Core behavior selectors, typically chained after or before the provider selector method
optionsBuilder.UseNpgsql(_dbConnection);
optionsBuilder .UseSqlServer(connectionString, providerOptions=>providerOptions.CommandTimeout(60)) .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
The DbContextOptions
can be supplied to the DbContext
by overriding the OnConfiguring
method or externally via a constructor argument.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { …… }
public class BloggingContext : DbContext { public BloggingContext(DbContextOptions<BloggingContext> options) : base(options) { } public DbSet<Blog> Blogs { get; set; } }
If both are used, OnConfiguring
is applied last and can overwrite options supplied to the constructor argument.
The base constructor of DbContext also accepts the non-generic version of DbContextOptions
, but using the non-generic version is not recommended for applications with multiple context types.
Your application can now pass the DbContextOptions
when instantiating a context, as follows:
var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>(); optionsBuilder.UseSqlite("Data Source=blog.db"); using (var context = new BloggingContext(optionsBuilder.Options)) { // do stuff }
public class BloggingContext : DbContext { public DbSet<Blog> Blogs { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite("Data Source=blog.db"); } }
An application can simply instantiate such a context without passing anything to its constructor:
using (var context = new BloggingContext()) { // do stuff }
Adding the DbContext
to dependency injection:
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<BloggingContext>(options => options.UseSqlite("Data Source=blog.db")); }
This requires adding a constructor argument to your DbContext type that accepts DbContextOptions<TContext>
.
public class BloggingContext : DbContext { public BloggingContext(DbContextOptions<BloggingContext> options) :base(options) { } public DbSet<Blog> Blogs { get; set; } } //Application code (in ASP.NET Core): public class MyController { private readonly BloggingContext _context; public MyController(BloggingContext context) { _context = context; } ... } //Application code (using ServiceProvider directly, less common): using (var context = serviceProvider.GetService<BloggingContext>()) { // do stuff } var options = serviceProvider.GetService<DbContextOptions<BloggingContext>>();
Avoiding DbContext threading issues
Implicitly sharing DbContext instances across multiple threads via dependency injection