时间:2021-07-01 10:21:17 帮助过:38人阅读
在将数据移入和移出数据库时,重要的是要跟踪所做的更改。否则,该数据将不会被写回到数据库中。同样,您必须插入创建的新对象并删除所有删除的对象。
您可以随着对象模型的每次更改来更改数据库,但是这可能导致许多非常小的数据库调用,这最终会非常缓慢。此外,它要求您为整个交互打开一个事务,如果您的业务事务跨越多个请求,则这是不切实际的。如果您需要跟踪已读取的对象,从而避免不一致的读取,则情况甚至更糟。
工作单元会跟踪您在业务交易过程中可能影响数据库的所有操作。完成后,它会计算出由于工作而需要更改数据库的所有工作。英文原文请参考:EAA的P。
EF Core的典型工作单元包括(重点理解这段,有助于我们对EF Core工作原理的理解):
重要知识点:
在许多 Web 应用程序中,每个 HTTP 请求都对应于单个工作单元。 这使得上下文生存期与请求的生存期相关。
使用依赖关系注入配置 ASP.NET Core 应用程序。 可以使用 Startup.cs
的 ConfigurureServices
方法中的 AddDbContext 将 EF Core 添加到此配置。 例如:
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddDbContext<ApplicationDbContext>( options => options.UseSqlServer("name=ConnectionStrings:DefaultConnection")); }
此示例将名为 ApplicationDbContext
的 DbContext
子类注册为 ASP.NET Core 应用程序服务提供程序(也称为 依赖关系注入容器)中的作用域服务。
options => options.UseSqlServer上下文配置为使用 SQL Server 数据库提供程序,
"name=ConnectionStrings:DefaultConnection"表示将从 ASP.NET Core 配置读取连接字符串。 在 ConfigureServices
中的何处调用 AddDbContext
通常不重要。
ApplicationDbContext
(数据库上下文)类必须公开具有 DbContextOptions<ApplicationDbContext>
参数的公共构造函数。 这是将 AddDbContext
的上下文配置传递到 DbContext
的方式。 例如:
public class ApplicationDbContext : DbContext { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } }
然后,ApplicationDbContext
可以通过构造函数注入在 ASP.NET Core 控制器或其他服务中使用。 例如:
1 public class MyController 2 { 3 private readonly ApplicationDbContext _context; 4 5 public MyController(ApplicationDbContext context) 6 { 7 _context = context; 8 } 9 }
最终结果是为每个请求创建一个 ApplicationDbContext
实例,并传递给控制器,以在请求结束后释放前执行工作单元。
可以按照常规的 .NET 方式构造 DbContext
实例,例如,使用 C# 中的 new
。 可以通过重写 OnConfiguring
方法或通过将选项传递给构造函数来执行配置。 例如:
1 public class ApplicationDbContext : DbContext 2 { 3 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 4 { 5 optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test"); 6 } 7 }
通过此模式,还可以轻松地通过 DbContext
构造函数传递配置(如连接字符串)。 例如:
1 public class ApplicationDbContext : DbContext 2 { 3 private readonly string _connectionString; 4 5 public ApplicationDbContext(string connectionString) 6 { 7 _connectionString = connectionString; 8 } 9 10 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 11 { 12 optionsBuilder.UseSqlServer(_connectionString); 13 } 14 }
或者,可以使用 DbContextOptionsBuilder
创建 DbContextOptions
对象,然后将该对象传递到 DbContext
构造函数。 这使得为依赖关系注入配置的 DbContext
也能显式构造。 例如,使用上述为 ASP.NET Core 的 Web 应用定义的 ApplicationDbContext
时:
1 public class ApplicationDbContext : DbContext 2 { 3 public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) 4 : base(options) 5 { 6 } 7 }
可以创建 DbContextOptions
,并可以显式调用构造函数:
var contextOptions = new DbContextOptionsBuilder<ApplicationDbContext>() .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test") .Options; using var context = new ApplicationDbContext(contextOptions);
某些应用程序类型(例如 ASP.NET Core Blazor)使用依赖关系注入,但不创建与所需的 DbContext
生存期一致的服务作用域。 即使存在这样的对齐方式,应用程序也可能需要在此作用域内执行多个工作单元。 例如,单个 HTTP 请求中的多个工作单元。在这些情况下,可以使用 AddDbContextFactory 来注册工厂以创建 DbContext
实例。 例如:
1 public void ConfigureServices(IServiceCollection services) 2 { 3 services.AddDbContextFactory<ApplicationDbContext>(options => 4 options.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test")); 5 }
ApplicationDbContext
类必须公开具有 DbContextOptions<ApplicationDbContext>
参数的公共构造函数。 此模式与上面传统 ASP.NET Core 部分中使用的模式相同。
1 public class ApplicationDbContext : DbContext 2 { 3 public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) 4 : base(options) 5 { 6 } 7 }
然后,可以通过构造函数注入在其他服务中使用 DbContextFactory
工厂。 例如:
1 private readonly IDbContextFactory<ApplicationDbContext> _contextFactory; 2 3 public MyController(IDbContextFactory<ApplicationDbContext> contextFactory) 4 { 5 _contextFactory = contextFactory; 6 }
然后,可以使用注入的工厂在服务代码中构造 DbContext 实例。 例如:
1 public void DoSomething() 2 { 3 using (var context = _contextFactory.CreateDbContext()) 4 { 5 // ... 6 } 7 }
请注意,以这种方式创建的 DbContext
实例并非由应用程序的服务提供程序进行管理,因此必须由应用程序释放。
所有 DbContext
配置的起始点都是 DbContextOptionsBuilder。 可以通过三种方式获取此生成器:
AddDbContext
和相关方法中OnConfiguring
中new
显式构造 上述各节显示了其中每个示例。 无论生成器来自何处,都可以应用相同的配置。 此外,无论如何构造上下文,都将始终调用 OnConfiguring
。 这意味着即使使用 AddDbContext
,OnConfiguring
也可用于执行其他配置。
每个 DbContext
实例都必须配置为使用一个且仅一个数据库提供程序。 (DbContext
子类型的不同实例可用于不同的数据库提供程序,但单个实例只能使用一个。)使用特定的 Use*
" 调用配置数据库提供程序。 例如,若要使用 SQL Server 数据库提供程序:
1 public class ApplicationDbContext : DbContext 2 { 3 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 4 { 5 optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test"); 6 } 7 }
这些 Use*
" 方法是由数据库提供程序实现的扩展方法。 这意味着必须先安装数据库提供程序 NuGet 包,然后才能使用扩展方法。
EF Core 数据库提供程序广泛使用扩展方法。 如果编译器指示找不到方法,请确保已安装提供程序的 NuGet 包,并且你在代码中已有 using Microsoft.EntityFrameworkCore;
。
下表包含常见数据库提供程序的示例:
|
|
|
|||
SQL Server 或 Azure SQL | .UseSqlServer(connectionString) | Microsoft.EntityFrameworkCore.SqlServer | |||
Azure Cosmos DB | .UseCosmos(connectionString, databaseName) | Microsoft.EntityFrameworkCore.Cosmos | |||
SQLite | .UseSqlite(connectionString) | Microsoft.EntityFrameworkCore.Sqlite | |||
EF Core 内存中数据库 | .UseInMemoryDatabase(databaseName) | Microsoft.EntityFrameworkCore.InMemory | |||
PostgreSQL* | .UseNpgsql(connectionString) | Npgsql.EntityFrameworkCore.PostgreSQL | |||
MySQL/MariaDB* | .UseMySql((connectionString) | Pomelo.EntityFrameworkCore.MySql | |||
Oracle* | .UseOracle(connectionString) | Oracle.EntityFrameworkCore |
Entity Framework Core 不支持在同一 DbContext
实例上运行多个并行操作。 这包括异步查询的并行执行以及从多个线程进行的任何显式并发使用。 因此,始终立即 await
异步调用,或对并行执行的操作使用单独的 DbContext
实例。
当 EF Core 检测到尝试同时使用 DbContext
实例的情况时,你将看到 InvalidOperationException
Entity Framework Core - DbContext配置和初始化
标签:cat 个数 异步查询 style sqli memory ora 注销 exce