首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >迁移过程中的实体框架内存不足- C#

迁移过程中的实体框架内存不足- C#
EN

Stack Overflow用户
提问于 2017-12-19 11:29:11
回答 2查看 185关注 0票数 0

我正在执行一个迁移过程,它必须将所有信息从一个数据库复制到另一个数据库。当它开始运行时,似乎一切都很好,问题是当进程到达一个复杂的表时。

这张桌子是特别的,因为它有一些特性。我将用一个例子更好地解释它:

  • entityX是一个人。
  • entityX可以有entityY(id帐户)
  • entityX可以有很多entityZ(朋友)
  • entityX可以有很多entityV(地址)
  • entityX可以拥有大量的entityW(汽车)

当进程插入1159 entityX及其依赖项时,会出现内存不足异常,更少。

在每个entityX之后,我们使用一个函数调用CleanMemory,它使用GarbageCollector来清理内存。

这个问题有什么解决办法吗?

代码语言:javascript
复制
public static void LoadExample(origin agmCtx, destinity.AgroPelayoEntities agpCtx)
    {//GET ALL THE INFO THAT WE NEED 
        List<EntityX> listOriginX = agmCtx.EntityX.AsNoTracking().ToList();

        foreach (EntityX  ent in list)
        {

            ///LISTS INSERTS//////
            List<destinityEntityX> listInsert = new List<destinity.EntityX>();
            List<destinity.EntityY> listInsertY = new List<destinity.EntityY>();
            List<destinity.EntityZ> listInsertZ = new List<destinity.EntityZ>();
            List<destinity.EntityV> listInsertV = new List<destinity.EntityV>();
            List<destinity.EntityW> listInsertW = new List<destinity.EntityW>();

            ///LISTS UPDATES//////
            List<destinity.EntityX> listUpdate = new List<destinity.EntityX>();

                Boolean exists = listOriginX.Any(e => (e.n_id == ent.n_id));
                if (!exists)
                {
                    //HERE GOES CODE TO CREATE NEW ENTITY AND HIS CHILD(EntityY,List<listInsertZ>, List<EntityV>....)
                    listInsertY.Add(newEntityW);
                    listInsertY.Add(newEntityV);
                    listInsertY.Add(newEntityZ);
                    listInsertY.Add(newEntityY);
                    listInsert.Add(newEntityX);
                }
                else
                {
                    //MODIFY TO HAVE NEW INFO

                    listUpdateV.Add(oldEntityV_Modified);


                }

                int batchSizeX = ClassCommonFuncts.GetNumBatchCount(listInsert.Count());
                int batchSizeY= ClassCommonFuncts.GetNumBatchCount(listInsertY.Count());
                int batchSizeZ = ClassCommonFuncts.GetNumBatchCount(listInsertZ.Count());
                int batchSizeV = ClassCommonFuncts.GetNumBatchCount(listInsertV.Count());
                int batchSizeW = ClassCommonFuncts.GetNumBatchCount(listInsertW.Count());

                int batchSizeUpdateX = ClassCommonFuncts.GetNumBatchCount(listUpdateV.Count());


                agpCtx.BulkInsert<destinity.EntityW>(listInsertW, bulk => bulk.BatchSize = batchSizeW);
                agpCtx.BulkInsert<destinity.EntityV>(listInsertV, bulk => bulk.BatchSize = batchSizeV);
                agpCtx.BulkInsert<destinity.EntityZ>(listInsertZ, bulk => bulk.BatchSize = batchSizeZ);
                agpCtx.BulkInsert<destinity.EntityY>(listInsertY, bulk => bulk.BatchSize = batchSizeY);
                agpCtx.BulkInsert<destinity.EntityX>(listInsert, bulk => bulk.BatchSize = batchSizeX);

                agpCtx.BulkUpdate<destinity.EntityX>(listUpdate, bulk => bulk.BatchSize = batchSizeUpdateX);

                ClassCommonFuncts.CleanMemory();


        }


    }

函数CleanMemory

代码语言:javascript
复制
[DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
        private static extern int SetProcessWorkingSetSize(IntPtr process, int minimumWorkingSetSize, int maximumWorkingSetSize);
        public static void CleanMemory()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
        }

函数GetNumBatchCount

代码语言:javascript
复制
public static int GetNumBatchCount(decimal records)
        {
            if (records > 1000000)
            {
                return (int)Math.Ceiling((double)records / 1000);
            }
            else if (records > 500000)
            {
                return (int)Math.Ceiling((double)records / 100);
            }
            else if (records > 100000)
            {
                return (int)Math.Ceiling((double)records / 50);
            }
            else if (records > 5000)
            {
                return (int)Math.Ceiling((double)records  / 10);
            }
            else
            {
                return (int)Math.Ceiling((double)records / 1);
            }

        }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-01-03 15:40:20

最后的解决办法是“简单”。问题是EntityY与另一个实体(1到n)有关系,然后当应用程序运行超过1000 EntityX时,抛出OutOfMemory异常。

我修正了它,把它们分成几个小组,例如按年龄和男性分组。(就我而言,我做了另一组)

票数 0
EN

Stack Overflow用户

发布于 2017-12-19 12:52:45

不是长期的解决办法。首先,尝试为您的列表设置容量。

这也是一个不好的做法,调用GC在适当的地方,你做了。

还有一件事。在每一次迭代中创建新列表都是错误的做法,在类似于此内存泄漏的代码中,预计会出现这种情况。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47886018

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档