سؤال

أريد إعادة استخدام عنصر ذاكرة التخزين المؤقت لـ ASP.NET عند لمس ملف معين، ولكن التعليمة البرمجية التالية لا تعمل:

                       HttpContext.Current.Cache.Insert(
                            "Key",
                            SomeObject,
                            new CacheDependency(Server.MapPath("SomeFile.txt")),
                            DateTime.MaxValue,
                            TimeSpan.Zero,
                            CacheItemPriority.High,
                            null);

يبدو أن "SomeFile.txt" لا يتم تحديده عند الضغط على ذاكرة التخزين المؤقت، ولا يؤدي تعديله إلى إبطال هذا العنصر.

ما الخطأ الذي افعله؟

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

المحلول

تحليل حل المشكلة:

وكانت هذه مشكلة فريدة من نوعها ومثيرة للاهتمام، لذلك أنا ذاهب لتوثيق السبب والحل هنا بمثابة الإجابة للباحثين في المستقبل.

وكان شيء تركت في سؤالي أن هذا الإدراج مخبأ كان يحدث في فئة خدمة تنفيذ نمط المفرد.

في وباختصار يمكن القول:

public class Service 
{
        private static readonly Service _Instance = new Service();
        static Service () { }
        private Service () { }

        public static Service Instance
        {
            get { return _Instance; }
        }

        // The expensive data that this service exposes      
        private someObject _data = null;

        public someObject Data
        {
            get
            {
                 if (_data == null)
                     loadData();
                 return _data;
            }
        }


        private void loadData()
        {
            _data = GetFromCache();
            if (_data == null)
            {
                 // Get the data from our datasource
                 _data = ExpensiveDataSourceGet();

                 // Insert into Cache
                 HttpContext.Current.Cache.Insert(etc);
            }
        }
}

قد يكون واضحا للبعض، ولكن السبب الرئيسي هنا هو تحميل كسول داخل نمط المفرد. تم القبض I حتى يصل التفكير في أن ذاكرة التخزين المؤقت لم يتم إبطالها، وأنني نسيت أن حالة المفرد سوف استمر لطالما كانت العملية المنفذة على قيد الحياة.

وCache.Insert لديه الزائد الذي يسمح لك بتحديد معالج الحدث عندما يتم إزالة العنصر ذاكرة التخزين المؤقت، وكان أول اختبار لي لإنشاء معالج وهمية وتعيين نقطة توقف داخله. مرة واحدة رأيت أن ذاكرة التخزين المؤقت تم تبرئته، أدركت أن "_data" لم يتم إعادة تعيين فارغة، وبالتالي فإن الطلب التالي إلى المفرد تحميل القيمة المحملة كسول.

في الشعور، وكنت التخزين المؤقت مزدوج، على الرغم من مخبأ المفرد لم يدم طويلا جدا، لكنها طويلة بما فيه الكفاية لتكون مزعجة.

والحل؟

 HttpContext.Current.Cache.Insert(
     "Key",
      SomeObject,
      new CacheDependency(Server.MapPath("SomeFile.txt")),
      DateTime.MaxValue,
      TimeSpan.Zero,
      CacheItemPriority.High,
      delegate(string key, object value, CacheItemRemovedReason reason)
      {
          _data = null;
      }
 );

وعندما يتم مسح ذاكرة التخزين المؤقت، ودولة داخل المفرد يجب أيضا أن يتم مسح ... حل المشكلة.

والدرس المستفاد هنا؟ لا تضع الدولة في المفرد.

نصائح أخرى

هل ASP.NET يعمل تحت حساب مع الأذونات المناسبة للملف المحدد في CacheDependency؟ إذا لم يكن كذلك، ثم قد يكون هذا أحد الأسباب التي تجعل CacheDependency لا يعمل بشكل صحيح.

وأعتقد أنك سوف تحتاج إلى تحديد مسار:

var d = new CacheDependency(Server.MapPath("SomeFile.txt"));

وإضافة قبل مع ~\App_Data حسب الحاجة.

الكود الخاص بك يبدو جيدًا بالنسبة لي.ومع ذلك، بخلاف هذا المقتطف، يمكن أن يحدث أي شيء.

  • هل تقوم بإعادة الإدراج في كل إعادة نشر بأي فرصة؟

  • حاول جعل تبعية ذاكرة التخزين المؤقت الخاصة بك بمثابة حقل فئة، والتحقق منها في كل إعادة نشر.قم بتعديل الملف بينهما ومعرفة ما إذا كان قد تم تسجيله على أنه "تم التغيير".على سبيل المثال:

    public partial class _Default : System.Web.UI.Page
    {
       CacheDependency dep;
    
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            dep = new CacheDependency(Server.MapPath("SomeFile.txt"));
            HttpContext.Current.Cache.Insert(
                        "Key",
                        new Object(),
                        dep,
                        DateTime.MaxValue,
                            TimeSpan.Zero, CacheItemPriority.High, null);
        }
    
    
        if (dep.HasChanged)
            Response.Write("changed!");
        else
            Response.Write("no change :(");   }}
    

والطريقة الوحيدة وأنا قادرة على إعادة إنتاج هذا السلوك إذا كان المسار المقدمة إلى منشئ CacheDependency غير موجود. سوف CacheDependency لا بطرح استثناء في حالة عدم وجود المسار، لذلك يمكن أن يكون مضللا بعض الشيء.

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