Entity Framework 6.1 - 如何使用异步?
Entity Framework 6.1 - how to use async?
我正在使用 .NET 4.8 和 Entity Framework 6.1 开发一个项目。
到目前为止,我们主要使用同步代码,但我们想开始使用异步。为此,我们需要进行异步数据库操作。
不过,我在处理交易部分时遇到了困难
- EF 6.1 具有查询的异步操作:
ToListAync()
、SingleOrDefaultAsync()
、SaveChangesAsync()
、等等
- 但不适用于交易:只有
Database.BeginTransaction()
和 DbContextTransaction.Commit()
需要交易时怎么办?
- 仅使用同步代码(使用
SaveChanges
、BeginTransaction()
和 Commit()
)?
- 混合同步和异步(使用
SaveChangesAsync()
、BeginTransaction()
和 Commit()
)?
只需进行所有更改,然后使用 SaveChangesAsync()
,所有操作都在一个事务中提交。失败时,将抛出异常并回滚所有更改。通常你不需要手动控制交易。
看这里:
https://docs.microsoft.com/en-us/ef/core/saving/transactions
默认交易行为
注意:Microsoft 只谈论 SaveChanges
但同样适用于 SaveChangesAsync
。
典型代码:
using Microsoft.EntityFrameworkCore;
using (var ef = new DbCdr.Context(logDebugToConsole: true))
{
////ADD
DbCdr.CCLog new1 = new DbCdr.CCLog()
{
Time = DateTime.Now,
ConcurrentCalls = 99
};
// Begins tracking the given entity, and any other reachable entities that are not already being tracked, in the Added state such that they will be inserted into the database when SaveChanges() is called.
ef.CCLogs.Add(new1);
//// DELETE
// actually queries the Db, thus use Async
var toDel = await ef.Cdrs.Where(_ => _.ServerId == 1).FirstAsync();
// Begins tracking the given entity in the Deleted state such that it will be removed from the database when SaveChanges() is called.
ef.Cdrs.Remove(toDel);
//// UPDATE
///// actually queries the Db, thus use Async
var toUpdate = await ef.Cdrs.OrderByDescending(_ => _.StartTime).FirstAsync();
toUpdate.ReleaseTime = DateTime.Now; // changes will be tracked and saved on SaveChanges()
await ef.SaveChangesAsync(); // all will actually be done here in a transaction. Or if something fails throw Exception and ROLLBACK
}
Remove()
和 Add()
函数不是 Asnyc,因为它们只启动 Tracking
并且不执行任何查询。
要深入了解 EF 的工作原理,您可以像这样在上下文中启用日志记录,这会为您提供已执行查询和操作(例如“启动事务”)的非常详细的输出:
public readonly bool LogToConsole;
public Context(bool logDebugToConsole = false)
{
LogToConsole = logDebugToConsole;
ConnString = $"User ID=xxxxxx;Password=xxxxxx;Host=xxxxx;Port=xxxxx;Database=xxxxxx; Pooling = true;";
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseNpgsql(connectionString: ConnString);
if (LogToConsole)
optionsBuilder.LogTo(Console.WriteLine);
}
}
给EntityFramework新手的更多建议:
- 上下文旨在短暂存在,如果需要,也请使用池,避免一直重新打开 tcp 连接。切勿使用延长的上下文。
- 等待ANY 异步函数ALWAYS.
我正在使用 .NET 4.8 和 Entity Framework 6.1 开发一个项目。
到目前为止,我们主要使用同步代码,但我们想开始使用异步。为此,我们需要进行异步数据库操作。
不过,我在处理交易部分时遇到了困难
- EF 6.1 具有查询的异步操作:
ToListAync()
、SingleOrDefaultAsync()
、SaveChangesAsync()
、等等 - 但不适用于交易:只有
Database.BeginTransaction()
和DbContextTransaction.Commit()
需要交易时怎么办?
- 仅使用同步代码(使用
SaveChanges
、BeginTransaction()
和Commit()
)? - 混合同步和异步(使用
SaveChangesAsync()
、BeginTransaction()
和Commit()
)?
只需进行所有更改,然后使用 SaveChangesAsync()
,所有操作都在一个事务中提交。失败时,将抛出异常并回滚所有更改。通常你不需要手动控制交易。
看这里: https://docs.microsoft.com/en-us/ef/core/saving/transactions
默认交易行为
注意:Microsoft 只谈论 SaveChanges
但同样适用于 SaveChangesAsync
。
典型代码:
using Microsoft.EntityFrameworkCore;
using (var ef = new DbCdr.Context(logDebugToConsole: true))
{
////ADD
DbCdr.CCLog new1 = new DbCdr.CCLog()
{
Time = DateTime.Now,
ConcurrentCalls = 99
};
// Begins tracking the given entity, and any other reachable entities that are not already being tracked, in the Added state such that they will be inserted into the database when SaveChanges() is called.
ef.CCLogs.Add(new1);
//// DELETE
// actually queries the Db, thus use Async
var toDel = await ef.Cdrs.Where(_ => _.ServerId == 1).FirstAsync();
// Begins tracking the given entity in the Deleted state such that it will be removed from the database when SaveChanges() is called.
ef.Cdrs.Remove(toDel);
//// UPDATE
///// actually queries the Db, thus use Async
var toUpdate = await ef.Cdrs.OrderByDescending(_ => _.StartTime).FirstAsync();
toUpdate.ReleaseTime = DateTime.Now; // changes will be tracked and saved on SaveChanges()
await ef.SaveChangesAsync(); // all will actually be done here in a transaction. Or if something fails throw Exception and ROLLBACK
}
Remove()
和 Add()
函数不是 Asnyc,因为它们只启动 Tracking
并且不执行任何查询。
要深入了解 EF 的工作原理,您可以像这样在上下文中启用日志记录,这会为您提供已执行查询和操作(例如“启动事务”)的非常详细的输出:
public readonly bool LogToConsole;
public Context(bool logDebugToConsole = false)
{
LogToConsole = logDebugToConsole;
ConnString = $"User ID=xxxxxx;Password=xxxxxx;Host=xxxxx;Port=xxxxx;Database=xxxxxx; Pooling = true;";
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseNpgsql(connectionString: ConnString);
if (LogToConsole)
optionsBuilder.LogTo(Console.WriteLine);
}
}
给EntityFramework新手的更多建议:
- 上下文旨在短暂存在,如果需要,也请使用池,避免一直重新打开 tcp 连接。切勿使用延长的上下文。
- 等待ANY 异步函数ALWAYS.