【问题标题】:Setting fetch size in entity framework在实体框架中设置获取大小
【发布时间】:2014-02-18 18:10:08
【问题描述】:

我正在转换 ado.net 代码以使用 EF。在我的 ado.net 代码中,我设置了dataReader.FetchSize = command.RowSize * 1000,这大大提高了默认提取大小的性能。 当我将我的代码转换为 EF 时,性能与我没有指定获取大小的 ado.net 代码相当,即它在大型记录上非常慢。

我可以通过任何方式指定获取大小以在 EF 中检索记录吗?

【问题讨论】:

    标签: ado.net oracle11g entity-framework-5 odp.net ado.net-entity-data-model


    【解决方案1】:

    您可以在使用实体框架时在注册表或 .NET 配置文件中设置 ODP.NET FetchSize。这将使您的所有 ODP.NET 实例(在 Registry 的情况下)或整个应用程序(在 app/web.config 的情况下)的 FetchSize 标准化。

    http://docs.oracle.com/cd/E48297_01/doc/win.121/e41125/featConfig.htm

    克里斯蒂安·谢伊

    甲骨文

    【讨论】:

    • 我已经做到了,它可以工作,我只是想能够在代码中做到这一点。无论如何,您的答案是正确的,所以我将其标记为这样。
    【解决方案2】:

    我遇到了类似的问题,但不想更改整体 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;
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-01-02
      • 1970-01-01
      • 1970-01-01
      • 2012-09-20
      • 2013-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-22
      相关资源
      最近更新 更多