數據庫連接字符串
在 ASP.NET Core 添加配置片段:
{
"ConnectionStrings": {
"BloggingDatabase": "Server=(localdb)\\mssqllocaldb;Database=EFGetStarted.ConsoleApp.NewDb;Trusted_Connection=True;"
}
}
然后,配置對應的DbContext:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<BloggingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("BloggingDatabase")));
}
日志記錄
EF Core 默認會與 ASP.NET Core的日志提供程序一起工作,只需要使用AddDbContext
或AddDbContextPool
添加服務即可。
除此之外,還可以手工添加日志記錄。
首先,創建LoggerFactory的單例:
public static readonly LoggerFactory MyLoggerFactory
= new LoggerFactory(new[] {new ConsoleLoggerProvider((_, __) => true, true)});
然后,通過DbContextOptionsBuilder
注冊此單例:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseLoggerFactory(MyLoggerFactory) // Warning: Do not create a new ILoggerFactory instance each time
.UseSqlServer(
@"Server=(localdb)\mssqllocaldb;Database=EFLogging;Trusted_Connection=True;ConnectRetryCount=0");
如果你只想記錄想要的日志,例如數據操作語句,可以在ILoggerProvider中進行配置:
public static readonly LoggerFactory MyLoggerFactory
= new LoggerFactory(new[]
{
new ConsoleLoggerProvider((category, level)
=> category == DbLoggerCategory.Database.Command.Name
&& level == LogLevel.Information, true)
});
配置彈性連接
EF Core 可以根據不同的數據庫失敗,制定不同的執行策略,例如故障自動重試等。
針對SQL Server,它知道可以重試的異常類型,並且具有合理的默認值的最大重試,重試次數等之間的延遲。
配置如下:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(
@"Server=(localdb)\mssqllocaldb;Database=EFMiscellanous.ConnectionResiliency;Trusted_Connection=True;ConnectRetryCount=0",
options => options.EnableRetryOnFailure());
}
也可在Startup中配置:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<PicnicContext>(
options => options.UseSqlServer(
"<connection string>",
providerOptions => providerOptions.EnableRetryOnFailure()));
}
你也可以自定義執行策略:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseMyProvider(
"<connection string>",
options => options.ExecutionStrategy(...));
}
自動重試與事物
對於執行自動重試策略來說,每一次調用context.SaveChanges()
方法將會當做一個重試單元。如果你的事物中有多個SaveChanges操作,配置的自動重試策略將會拋出異常,解決方法是使用委托來手動調用執行策略。代碼如下:
using (var db = new BloggingContext())
{
var strategy = db.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using (var context = new BloggingContext())
{
using (var transaction = context.Database.BeginTransaction())
{
context.Blogs.Add(new Blog {Url = "http://blogs.msdn.com/dotnet"});
context.SaveChanges();
context.Blogs.Add(new Blog {Url = "http://blogs.msdn.com/visualstudio"});
context.SaveChanges();
transaction.Commit();
}
}
});
}
此方法同樣適用於環境事物:
using (var context1 = new BloggingContext())
{
context1.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/visualstudio" });
var strategy = context1.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using (var context2 = new BloggingContext())
{
using (var transaction = new TransactionScope())
{
context2.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
context2.SaveChanges();
context1.SaveChanges();
transaction.Complete();
}
}
});
}
自動重試策略需要考慮冪等性問題,防止數據添加重復等誤操作。EF Core 引入了一種狀態檢查機制,可以幫助我們實現是否執行成功的檢測:
using (var db = new BloggingContext())
{
var strategy = db.Database.CreateExecutionStrategy();
var blogToAdd = new Blog {Url = "http://blogs.msdn.com/dotnet"};
db.Blogs.Add(blogToAdd);
strategy.ExecuteInTransaction(db,
operation: context =>
{
context.SaveChanges(acceptAllChangesOnSuccess: false);
},
verifySucceeded: context => context.Blogs.AsNoTracking().Any(b => b.BlogId == blogToAdd.BlogId));
db.ChangeTracker.AcceptAllChanges();
}
DbContext配置項
DbContext必須有DbContextOptions實例能,Options的作用如下:
- 配置數據庫提供程序
- 連接字符串
- 數據庫提供程序級別的可選項
- EF Core級別的可選項
可以通過構造函數添加Options:
public class BloggingContext : DbContext
{
public BloggingContext(DbContextOptions<BloggingContext> options)
: base(options)
{ }
public DbSet<Blog> Blogs { get; set; }
}
也可以通過OnConfiguring方法進行配置:
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=blog.db");
}
}
使用依賴注入DbContext時,需要構造函數的方式進行配置,並在Startup中配置DbContext:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<BloggingContext>(options => options.UseSqlite("Data Source=blog.db"));
}
避免多線程操作
EF Core 提供了async/await操作,但是這是一個語法糖,它並不支持並行操作,這是由於數據庫連接的特性限制的,因此我們應避免針對同一個Context執行任何並行操作。
參考文檔
參考微軟 EF Core 使用文檔,詳情: