> 技术文档 > Entity Framework Core (EF Core) 中Database

Entity Framework Core (EF Core) 中Database

在 Entity Framework Core (EF Core) 中,Database属性的类型是DatabaseFacadeDatabaseFacade 是一个关键的门面类,提供对数据库相关操作的统一访问接口。它封装了与底层数据库交互的核心功能,包括连接管理、事务处理、执行原始 SQL 以及数据库迁移等操作。下面从功能、用法、常见场景和最佳实践几个方面详细解析:

1. 核心功能

DatabaseFacade 提供以下主要功能:

// 获取底层 DbConnectionvar connection = context.Database.GetDbConnection();// 检查连接状态if (context.Database.GetDbConnection().State != ConnectionState.Open){ await context.Database.OpenConnectionAsync();}// 执行连接相关操作var databaseName = context.Database.GetDbConnection().Database;
1.2 事务处理
// 开始事务await using var transaction = await context.Database.BeginTransactionAsync();try{ // 执行数据操作 context.Users.Add(new User { Name = \"John\" }); await context.SaveChangesAsync(); // 提交事务 await transaction.CommitAsync();}catch (Exception){ // 回滚事务 await transaction.RollbackAsync();}
1.3 执行原始 SQL
// 执行查询var users = await context.Users .FromSqlRaw(\"SELECT * FROM Users WHERE Age > {0}\", 18) .ToListAsync();// 执行非查询命令var rowsAffected = await context.Database.ExecuteSqlRawAsync( \"UPDATE Users SET LastLogin = GETDATE() WHERE Id = {0}\", 1);
1.4 数据库迁移
// 应用所有待迁移的更改await context.Database.MigrateAsync();// 检查是否需要迁移bool pendingMigrations = (await context.Database.GetPendingMigrationsAsync()).Any();// 创建数据库(如果不存在)await context.Database.EnsureCreatedAsync();
1.5 数据库状态检查
// 检查数据库是否存在bool exists = await context.Database.EnsureExistsAsync();// 检查数据库架构是否与模型匹配bool isCompatible = await context.Database.CanConnectAsync();

2. 获取 DatabaseFacade 实例

在 DbContext 中,可以通过 Database 属性访问 DatabaseFacade

public class ApplicationDbContext : DbContext{ public DbSet Users { get; set; } // 通过基类的 Database 属性访问 DatabaseFacade public void SomeMethod() { // 执行数据库操作 this.Database.ExecuteSqlRaw(\"UPDATE Users SET ...\"); }}

3. 常见应用场景

3.1 复杂查询优化

对于 EF Core 查询性能不佳的场景,使用原始 SQL:

var results = await context.Set() .FromSqlRaw(\"EXEC sp_GetComplexData @Param1, @Param2\", param1, param2) .ToListAsync();
3.2 批量操作

执行批量更新或删除:

await context.Database.ExecuteSqlRawAsync( \"DELETE FROM Orders WHERE OrderDate < {0}\", DateTime.Now.AddYears(-1));
3.3 数据库初始化与迁移

在应用启动时确保数据库和架构存在:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env){ using (var scope = app.ApplicationServices.CreateScope()) { var context = scope.ServiceProvider.GetRequiredService(); context.Database.Migrate(); // 应用所有迁移 } // 其他配置...}
3.4 分布式事务

结合 ADO.NET 使用分布式事务:

await using var transaction = await context.Database.BeginTransactionAsync();try{ // EF Core 操作 context.Users.Add(new User { Name = \"Alice\" }); await context.SaveChangesAsync(); // ADO.NET 操作(使用相同连接) var connection = context.Database.GetDbConnection(); using (var command = connection.CreateCommand()) { command.Transaction = transaction.GetDbTransaction(); command.CommandText = \"UPDATE Log SET Status = \'Processed\' WHERE Id = 1\"; await command.ExecuteNonQueryAsync(); } await transaction.CommitAsync();}catch (Exception){ await transaction.RollbackAsync(); throw;}

4. 高级用法

4.1 控制连接超时
context.Database.SetCommandTimeout(TimeSpan.FromMinutes(2)); // 设置 2 分钟超时
4.2 拦截数据库操作

通过自定义拦截器记录 SQL 执行时间:

public class SqlLoggingInterceptor : DbCommandInterceptor{ private readonly ILogger _logger; public SqlLoggingInterceptor(ILogger logger) { _logger = logger; } public override InterceptionResult ReaderExecuting( DbCommand command, CommandEventData eventData, InterceptionResult result) { _logger.LogInformation(\"Executing SQL: {Sql}\", command.CommandText); return base.ReaderExecuting(command, eventData, result); }}// 在 DbContext 中注册拦截器protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){ optionsBuilder.AddInterceptors(new SqlLoggingInterceptor(_logger));}
4.3 多数据库操作

在多个 DbContext 之间共享事务:

await using var transaction = await context1.Database.BeginTransactionAsync();try{ // 操作 context1 context1.Users.Add(new User { Name = \"Bob\" }); await context1.SaveChangesAsync(); // 操作 context2(使用相同事务) context2.Orders.Add(new Order { UserId = 1 }); await context2.SaveChangesAsync(); await transaction.CommitAsync();}catch (Exception){ await transaction.RollbackAsync(); throw;}

5. 注意事项

5.1 原始 SQL 的安全性

始终使用参数化查询,避免 SQL 注入:

// 安全写法await context.Database.ExecuteSqlRawAsync( \"UPDATE Users SET Name = {0} WHERE Id = {1}\", newName, id);// 不安全写法(避免)await context.Database.ExecuteSqlRawAsync( $\"UPDATE Users SET Name = \'{newName}\' WHERE Id = {id}\");
5.2 跨数据库兼容性

直接编写的 SQL 可能不支持多种数据库提供者(如 SQL Server 和 PostgreSQL 的语法差异)。

5.3 事务边界

确保事务的生命周期正确管理,避免长时间持有事务导致锁争用。

5.4 性能考虑

频繁调用 DatabaseFacade 方法可能影响性能,优先使用 EF Core 的 LINQ 查询。

总结

DatabaseFacade 是 EF Core 中连接应用程序和底层数据库的桥梁,提供了丰富的数据库操作功能。它在需要执行原始 SQL、管理事务或进行数据库迁移时特别有用。但在使用时应权衡其灵活性与潜在风险,遵循最佳实践以确保代码的安全性和可维护性。在大多数情况下,优先使用 EF Core 的高级 API,仅在必要时才通过 DatabaseFacade 进行底层操作。