EF Core 基礎知識


數據庫連接字符串

在 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的日志提供程序一起工作,只需要使用AddDbContextAddDbContextPool添加服務即可。

除此之外,還可以手工添加日志記錄。

首先,創建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 使用文檔,詳情:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM