我遇到了类似的问题,但不想更改整体 FetchSize,而是想更改每个查询的 FetchSize。
这是我想出的解决方案,也许这对某人有帮助。
它基本上使用CallContext 将参数传递给DbInterceptor。拦截器将覆盖查询命令所需的属性。
线程安全,支持嵌套范围。
这也可用于修改通过实体框架查询执行的命令的其他属性,以针对已定义的范围。
用法:
using (var context = new MyDbContext())
{
using (new OracleCommandContext(fetchSize: 1024 * 128))
{
// your query here
}
}
要覆盖的属性:
public class OracleCommandProperties
{
public long FetchSize { get; set; } = 524288; // oracle default value
}
调用上下文:
public class OracleCommandContext : IDisposable
{
private static readonly object sync = new object();
private readonly OracleCommandProperties previousCommandProperties;
private bool isDisposed;
static OracleCommandContext()
{
DbInterception.Add(new OracleCommandInterceptor());
}
public OracleCommandContext(long fetchSize)
{
lock (sync)
{
var commandProperties = new OracleCommandProperties();
if (TryGetProperties(out var previousProperties))
{
// when using nested OracleCommandContext, escalate the properties
previousCommandProperties = previousProperties;
commandProperties.FetchSize = Math.Max(previousProperties.FetchSize, fetchSize);
}
else
{
commandProperties.FetchSize = fetchSize;
}
CallContext.LogicalSetData(nameof(OracleCommandProperties), commandProperties);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~OracleCommandContext()
{
Dispose(false);
}
private void Dispose(bool disposing)
{
if (disposing)
{
if (!isDisposed)
{
lock (sync)
{
CallContext.LogicalSetData(nameof(OracleCommandProperties), previousCommandProperties);
}
isDisposed = true;
}
}
}
public static bool TryGetProperties(out OracleCommandProperties properties)
{
lock(sync)
{
if (CallContext.LogicalGetData(nameof(OracleCommandProperties)) is OracleCommandProperties oracleReaderProperties)
{
properties = oracleReaderProperties;
return true;
}
properties = null;
return false;
}
}
}
做实际工作的拦截器:
public class OracleCommandInterceptor : IDbCommandInterceptor
{
public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
}
public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
AdjustCommand(command);
}
public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
}
public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
AdjustCommand(command);
}
public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
}
public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
AdjustCommand(command);
}
private static void AdjustCommand(DbCommand command)
{
if (command is OracleCommand oracleCommand)
{
if (OracleCommandContext.TryGetProperties(out var properties))
{
oracleCommand.FetchSize = properties.FetchSize;
}
}
}
}