我有一个使用 EF Core 的 ASP.NET Core 2.2 应用程序。我有一个服务类,通常使用DbContext
用于任何 CRUD 操作。然而,在其中一种方法中(Assign
下面的方法)我需要使用存储过程。所以我使用以下代码。注意DbContext
被注入为Scoped
实例。
public class MyService : IMyService
{
private readonly MyDbContext _dbContext;
public MyService(MyDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<Employee> GetByID(int id)
{
return await _dbContext.Employees.FindById(id);
}
public async Task<int?> Assign(int itemID, int userID)
{
using (var cmd = _dbContext.Database.GetDbConnection().CreateCommand())
{
var p1 = new SqlParameter("@ItemId", SqlDbType.Int);
p1.Value = itemID;
var p2 = new SqlParameter("@UserID", SqlDbType.Int);
p2.Value = userID;
cmd.CommandText = "dbo.prcAssign";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(p1);
cmd.Parameters.Add(p2);
await _dbContext.Database.OpenConnectionAsync();
var result = await cmd.ExecuteScalarAsync();
if (result != null)
{
return Convert.ToInt32(result);
}
return null;
}
}
}
存储过程在内部使用 SQL 事务。我想知道是否需要显式关闭数据库连接Assign
方法或连接将在请求结束时由容器自动关闭?
问题是,由于存储过程正在使用事务,因此它在表上放置了读锁(我们实际上希望在表上使用读锁以避免获取脏数据)。该存储过程需要几毫秒的时间来执行,而我们几乎没有 50 个用户。然而,我们经常陷入僵局Employee
table:
System.Data.SqlClient.SqlException (0x80131904):事务(进程 ID 59)在锁资源上与另一个进程发生死锁,并已被选为死锁受害者。重新运行事务。
在System.Data.SqlClient.SqlConnection.OnError(SqlException异常,布尔breakConnection,操作1 wrapCloseInAction)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action
1 包裹CloseInAction)
在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject> stateObj,布尔 callerHasConnectionLock,布尔 asyncClose)
在System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSetbulkCopyHandler,TdsParserStateObject stateObj,Boolean&dataReady)
在 System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
在 System.Data.SqlClient.SqlDataReader.get_MetaData()
在System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,RunBehavior runBehavior,字符串resetOptionsString)
在 System.Data.SqlClient.SqlCommand.CompleteAsyncExecuteReader()
在System.Data.SqlClient.SqlCommand.InternalEndExecuteReader(IAsyncResult asyncResult,字符串endMethod)
在 System.Data.SqlClient.SqlCommand.EndExecuteReaderInternal (IAsyncResult asyncResult)
在 System.Data.SqlClient.SqlCommand.EndExecuteReader(IAsyncResult asyncResult) > 在 System.Threading.Tasks.TaskFactory1.FromAsyncCoreLogic(IAsyncResult iar, Func
2结束函数、动作1 endAction, Task
1 个承诺,布尔值需要同步)
--- 从先前抛出异常的位置开始的堆栈跟踪结束 ---
位于 D:\xxxx\Services\MyService.cs 中的 xxxxx.Services.MyService.Assign(Int32 itemID, Int32 userID):第 84 行
我想知道是否需要显式关闭数据库连接Assign
方法或连接将在请求结束时由容器自动关闭?
连接是否会在稍后自动关闭并不重要。遵循良好的编程实践,应该释放分配的资源(创建 -> 处置、打开 -> 关闭等)。
EF Core 内部会对每个需要打开连接的操作执行此操作,因此您最好也这样做,例如像这样的东西
await _dbContext.Database.OpenConnectionAsync();
try
{
var result = await cmd.ExecuteScalarAsync();
if (result != null)
{
return Convert.ToInt32(result);
}
return null;
}
finally
{
_dbContext.Database.CloseConnection();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)