سؤال

لقد واجهت بعض المشكلات مع LINQ-To-SQL حول استخدام الذاكرة.أنا أستخدمها في إحدى خدمات Windows لإجراء بعض المعالجة، وأقوم بتكرار كمية كبيرة من البيانات التي أسحبها من السياق.نعم - أعلم أنه يمكنني القيام بذلك باستخدام إجراء مخزن ولكن هناك أسباب تجعل هذا الحل أقل من مثالي.

على أية حال، ما أراه في الأساس هو أن الذاكرة لا يتم تحريرها حتى بعد الاتصال context.SubmitChanges().لذلك انتهى بي الأمر إلى القيام بكل أنواع الأشياء الغريبة مثل سحب 100 سجل فقط في المرة الواحدة، أو إنشاء عدة سياقات وجعلهم جميعًا يقومون بمهام منفصلة.إذا احتفظت بنفس الشيء DataContext واستخدامها لاحقًا لإجراء مكالمات أخرى، فهي تستهلك المزيد والمزيد من الذاكرة.حتى لو اتصلت Clear() على ال "var tableRows"المصفوفة التي يعودها لي الاستعلام، قم بتعيينها على قيمة خالية، ثم اتصل بها SYstem.GC.Collect() - لا يزال لا يحرر الذاكرة.

لقد قرأت الآن بعضًا عن كيفية الاستخدام DataContexts بسرعة والتخلص منها بسرعة، ولكن يبدو أنها يجب أن تكون وسيلة لإجبار السياق على تفريغ جميع بياناته (أو جميع بيانات التتبع الخاصة به لجدول معين) عند نقطة معينة لضمان أن الذاكرة مجانية.

هل يعرف أحد ما هي الخطوات التي تضمن تحرير الذاكرة؟

هل كانت مفيدة؟

المحلول

إذا لم تكن بحاجة إلى مجموعة تتبع الكائنات DataContext.ObjectTrackingEnabled ل خطأ شنيع.إذا كنت في حاجة إليها، يمكنك استخدام الانعكاس لاستدعاء الداخلي DataContext.ClearCache(), ، على الرغم من أنه يجب عليك أن تدرك أنه نظرًا لأنه داخلي، فإنه عرضة للاختفاء في الإصدار المستقبلي من إطار العمل.وبقدر ما أستطيع أن أقول، فإن إطار العمل نفسه لا يستخدمه ولكنه يفعل مسح ذاكرة التخزين المؤقت للكائن.

نصائح أخرى

يتتبع DataContext جميع الكائنات التي جلبها على الإطلاق.لن يتم إطلاق هذا حتى يتم جمع القمامة.وكذلك كما ينفذ IDisposable, ، يجب عليك الاتصال Dispose أو استخدم using إفادة.

هذا هو الطريق الصحيح للذهاب:

using(DataContext myDC = new DataContext)
{
  //  Do stuff
} //DataContext is disposed

كما يشير ديفيد، يجب عليك التخلص من DataContext باستخدام كتلة استخدام.

يبدو أن همك الأساسي هو إنشاء مجموعة من كائنات DataContext والتخلص منها.هذه هي الطريقة التي تم بها تصميم linq2sql.من المفترض أن يكون عمر DataContext قصيرًا.نظرًا لأنك تسحب الكثير من البيانات من قاعدة البيانات، فمن المنطقي أنه سيكون هناك الكثير من استخدام الذاكرة.أنت على الطريق الصحيح، من خلال معالجة بياناتك في أجزاء.

لا تخف من إنشاء الكثير من DataContexts.وهي مصممة لاستخدامها بهذه الطريقة.

شكرًا يا شباب - سوف أتحقق من طريقة ClearCache.فقط للتوضيح (للقراء المستقبليين)، كان الموقف الذي كنت أحصل فيه على استخدام الذاكرة شيئًا من هذا القبيل:

using(DataContext context = new DataContext())
{
   while(true)
   {
      int skipAmount = 0;
      var rows = context.tables.Select(x => x.Dept == "Dept").Skip(skipAmount).Take(100);

      //break out of loop when out of rows

      foreach(table t in rows)
      {
         //make changes to t   
      }

      context.SubmitChanges();
      skipAmount += rows.Count();

      rows.Clear();
      rows = null;

      //at this point, even though the rows have been cleared and changes have been
      //submitted, the context is still holding onto a reference somewhere to the
      //removed rows.  So unless you create a new context, memory usuage keeps on growing
   }
}

لقد واجهت للتو مشكلة مماثلة.في حالتي، ساعد في إنشاء خصائص DataContext.ObjectTrackingEnabled إلى كاذبة.ولكنها تعمل فقط في حالة التكرار خلال الصفوف كما يلي:

using (var db = new DataContext())
{
    db.ObjectTrackingEnabled = false;
    var documents = from d in db.GetTable<T>()
                     select d;
    foreach (var doc in documents)
    {
        ...
    }
}

إذا، على سبيل المثال، في الاستعلام لاستخدام أساليب ToArray() أو ToList() - أي تأثير

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top