Har*_*ngh 9 c# entity-framework entity-framework-core .net-core asp.net-core
我正在使用 .NET Core DI 来获取,DbContext并且在我的逻辑中,我还需要在 DB 上执行原始 SQL 命令,因此为此我创建DbCommand以执行这样的 SQL(只是一个示例查询,实际查询有点复杂,所以不写在这里为简单起见):
public string GetId()
{
var cmd = _context.Database.GetDbConnection().CreateCommand();
bool isOpen = cmd.Connection.State == ConnectionState.Open;
if (!isOpen)
{
cmd.Connection.Open();
}
cmd.CommandText = "Select TOP 1 ID from ABC;";
var result = (string)cmd.ExecuteScalar();
if (isOpen)
{
cmd.Connection.Close();
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,我在 DbContext 上使用GetDbConnection()和CreateCommand(),所以我是否需要显式处理任何这些命令的结果(或将它们包含在using语句中)?
也是if检查是否cmd.Connection.State是的块ConnectionState.Open必需的,如果DI与提供的DbContext,该连接将已经打开?
顺便说一句,如果重要的话,我们正在使用AddDbContextPool注册DbContext来启用DbContext池。
Iva*_*oev 15
我的问题是,我在 DbContext 上使用
GetDbConnection()和CreateCommand(),所以我是否需要明确处理任何这些命令的结果(或将它们包含在 using 语句中)?
这些是不同的,后者的答案是肯定的,前者的答案是否定的。
您只需要遵循简单的原则 - 分配资源的代码负责清理它。
GetDbConnection(如单词 所示Get)不创建DbConnection对象,而是返回DbContext实例在其生命周期中创建和使用的对象。在这种情况下,DbContext拥有DbConnection,因此您不应处置该对象(这样做可能会破坏所有者功能)。
另一方面,CreateCommand 确实创建了新DbCommand对象,因此现在您的代码拥有它并负责在不再需要时处理它。
同样的原则适用于Open/ Close。同样,您的代码不拥有该DbConnection对象,因此您必须使其保持与检索它时相同的状态。EF Core 在处理需要打开连接的命令时在内部执行此操作 - 在开始时打开它,完成后关闭它。除非它是从外部打开的,在这种情况下他们什么都不做。这正是上述原则 - 如果您的代码这样做Open,那么它应该这样做Close,否则什么都不做。
所以有问题的代码应该是这样的(请注意,您的代码的关闭逻辑中存在一个错误 - 调用的条件Close应该是!isOpen,与Open调用相同):
public string GetId()
{
using (var cmd = _context.Database.GetDbConnection().CreateCommand())
{
bool wasOpen = cmd.Connection.State == ConnectionState.Open;
if (!wasOpen) cmd.Connection.Open();
try
{
cmd.CommandText = "Select TOP 1 ID from ABC;";
var result = (string)cmd.ExecuteScalar();
return result;
}
finally
{
if (!wasOpen) cmd.Connection.Close();
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4545 次 |
| 最近记录: |