Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在每次迭代中处理内存中的对象_C#_Out Of Memory - Fatal编程技术网

C# 在每次迭代中处理内存中的对象

C# 在每次迭代中处理内存中的对象,c#,out-of-memory,C#,Out Of Memory,我正在编写一个对现有webjob的增强,它从一个表(外圈)获取记录并将其推送到另一个表(内圈)。外圈表中大约有7500万条记录,我想对要推送到内圈表的数据进行非常有选择性的选择。我使用一个存储过程来获取数据,对其进行分页,然后将其返回到内环中 public async Task ExecuteAsync( AMS360DbContext outerRingDb , MiddleTierCoreDbContext innerRingDb ,

我正在编写一个对现有webjob的增强,它从一个表(外圈)获取记录并将其推送到另一个表(内圈)。外圈表中大约有7500万条记录,我想对要推送到内圈表的数据进行非常有选择性的选择。我使用一个存储过程来获取数据,对其进行分页,然后将其返回到内环中

    public async Task ExecuteAsync(
        AMS360DbContext outerRingDb
        , MiddleTierCoreDbContext innerRingDb
        , SyncSupportDbContext syncDb
        , ILogger logger
        , CancellationToken cancellationToken)
    {
        var log = logger.CoverageSync(this);

        TelemetryClient telemetry = new TelemetryClient();
        log.SyncStarted("Coverages");
        var sw = Stopwatch.StartNew();

        var transformer = new AmsPolicyCoveragesTransformer();


        const string innerRingTable = InnerRingTables.PolicyCoverages;
        const string sourceSchema = "ams360";
        const string sourceStoredProcedure = "GetPolicyCoverages";

        try
        {
            const int pageSize = 50_000;
            var page = 0;
            bool hasMoreRecords;

            var rowVersion = await syncDb.GetInnerRingRowVersionAsync(innerRingTable, sourceSchema, sourceStoredProcedure);

            do
            {
                if (cancellationToken.IsCancellationRequested)
                    return;

                var index = page * pageSize;

                log.SyncInProgress(index, index + pageSize - 1);

                var rowVersionParam = new SqlParameter()
                {
                    ParameterName = "@RowVersion",
                    SqlDbType = SqlDbType.Timestamp,
                    Direction = ParameterDirection.Input,
                    Value = rowVersion != null ? BitConverter.GetBytes(Convert.ToUInt64(rowVersion)).Reverse().ToArray() : (object)DBNull.Value
                };

                var prms = new SqlParameter[]
                {
                    new SqlParameter("@PageStart", index),
                    new SqlParameter("@PageSize", pageSize),
                    rowVersionParam
                };

                var outerRingCoverages = await outerRingDb.Set<SpPolicyCoverages>()
                                                    .FromSqlRaw("EXEC ams360.GetPolicyCoverages @PageStart, @PageSize, @RowVersion", prms)
                                                    .ToListAsync(cancellationToken);

                page++;

                var transformed = transformer.Transform(outerRingCoverages).ToList();

                if (transformed.Any())
                {
                    await MergeToInnerRingAsync(innerRingDb, transformed, cancellationToken);

                    var latestVersion = outerRingCoverages.Max(x => x.RowVersion);

                    telemetry.TrackEvent("Inner Ring Sync - Coverages Success");

                    await syncDb.UpdateInnerRingSyncRowVersionAsync(innerRingTable, sourceSchema, sourceStoredProcedure, latestVersion.Value, cancellationToken);

                }

                hasMoreRecords = (outerRingCoverages.Count == pageSize);

            } while (hasMoreRecords);
        }
        catch (Exception ex)
        {
            log.SyncError("Coverages", ex);
            telemetry.TrackEvent("Inner Ring Sync - Coverages Error");
            throw;
        }

        log.SyncFinished("Coverages", sw.Elapsed);


    }
公共异步任务ExecuteAsync(
AMS360DbContext outerRingDb
,MiddleTierCoreDbContext innerRingDb
,SyncSupportDbContext syncDb
,ILogger记录器
,CancellationToken CancellationToken)
{
var log=logger.CoverageSync(this);
遥测客户端遥测=新的遥测客户端();
log.SyncStarted(“覆盖范围”);
var sw=Stopwatch.StartNew();
var变压器=新的AMSPOLICYCOVERAGESTRANSOR();
const string innerRingTable=InnerRingTables.policyCoverage;
常量字符串sourceSchema=“ams360”;
常量字符串sourceStoredProcedure=“GetPolicyCoverage”;
尝试
{
const int pageSize=50_000;
var-page=0;
布尔·哈斯莫尔唱片公司;
var rowVersion=await syncDb.GetInnerRingRowVersionAsync(innerRingTable、sourceSchema、SourceStoredProcess);
做
{
if(cancellationToken.IsCancellationRequested)
回来
变量索引=页面*页面大小;
同步进程(索引,索引+页面大小-1);
var rowVersionParam=新的SqlParameter()
{
ParameterName=“@RowVersion”,
SqlDbType=SqlDbType.Timestamp,
方向=参数方向。输入,
Value=rowVersion!=null?位转换器.GetBytes(Convert.ToUInt64(rowVersion)).Reverse().ToArray():(对象)DBNull.Value
};
var prms=新的SqlParameter[]
{
新的SqlParameter(“@PageStart”,索引),
新的SqlParameter(“@PageSize”,PageSize),
rowVersionParam
};
var outerringcoverage=await outerRingDb.Set()
.FromSqlRaw(“EXEC ams360.getPolicyCoverage@PageStart、@PageSize、@RowVersion”、prms)
.ToListSync(取消令牌);
page++;
var transformed=transformer.Transform(outerringcoverage.ToList();
if(transformed.Any())
{
等待合并连接同步(innerRingDb、转换、取消令牌);
var latestVersion=outerringcoverage.Max(x=>x.RowVersion);
TrackEvent(“内环同步-覆盖成功”);
等待syncDb.UpdateInnerRingSyncRowVersionAsync(innerRingTable、sourceSchema、SourceStoredProcess、latestVersion.Value、cancellationToken);
}
hasMoreRecords=(outerringcoverage.Count==页面大小);
}while(hasMoreRecords);
}
捕获(例外情况除外)
{
log.SyncError(“覆盖范围”,例如);
遥测.TrackEvent(“内环同步-覆盖错误”);
投
}
日志同步已完成(“覆盖范围”,软件运行时间);
}

我在这段代码中遇到的问题是,在迭代过程中的某个时刻,我遇到了OutofMemory异常。因此,我在查看诊断工具时,惊讶地发现,当我从SPPolicyCoverage表中获得50000条记录时,在内存中的堆中以及在下一次迭代中创建了50000个对象,内存中创建了100000个对象,并且随着这些对象继续在内存中累积,直到遇到OutofMemory异常。在每次迭代中处理对象(SPPolicyCoverage)的最佳方法是什么,这样我就不会遇到OutofMemory异常?请提前通知..谢谢。

SPPolicyCoverage是实体类型吗?如果是这样的话,这可能是一个问题,因为数据库上下文上没有禁用ChangeTracking。更改跟踪并没有什么不同,只是因为您使用的是FromSqlRaw。尝试禁用上下文上的更改跟踪,或使用
.AsNoTracking()

var outerringcoverage=await outerRingDb.Set()
.FromSqlRaw(“EXEC ams360.getPolicyCoverage@PageStart、@PageSize、@RowVersion”、prms)

.AsNoTracking()//不要将“处理”与“释放内存”混淆。他们不是一回事。“Disposing”在C#中的意思非常具体。这些上下文对象是什么?实体框架?根据您的描述,我认为这项工作应该在sql server中一起完成。为什么提取这么多数据只是为了将其推回到服务器,让服务器处理作业不是更有效吗。要使0获取/推送数据?但也许我误解了你的问题。我会尝试在每次迭代中创建“上下文”对象项的新实例。如果这些是实体框架上下文,objectstatemanager将在加载后保持它们的状态不变,或者至少手动将它们与上下文分离。您完全正确。导致问题的原因是没有添加.AsNoTracking()。非常感谢您的帮助:)
var outerRingCoverages = await outerRingDb.Set<SpPolicyCoverages>()
    .FromSqlRaw("EXEC ams360.GetPolicyCoverages @PageStart, @PageSize, @RowVersion", prms)
    .AsNoTracking() // <--
    .ToListAsync(cancellationToken);