PDA

View Full Version : Caching in CActiveDataProvicer



Muhammad-Ali
شنبه 25 مرداد 1393, 06:26 صبح
به نام خدا، سلام


$dependecy = new CDbCacheDependency('SELECT MAX(update_time) FROM {{post}}')
CActiveDataProvider(Post::model()->cache($duration, $dependecy, 2), array (
'criteria' => array (
'condition' => 'status = 1',
'order' => 'DESC create_time',
) 'pagination' => array (
'pageSize' => 20,
) ));
در کد بالا تعداد کوئری که باید از کش فراخوانی بشن رو برابر دو قرار گرفته. یکی برای count گرفتن از جدول جهت pagination و یکی هم برای واکشی رکوردها.
مشکل اینجاست، هنگامی که رکوردی در جدول دیتابیس نداشته باشیم، کوئری دوم اجرا نمیشه و نگه داشته میشه برای کوئری بعدی دیتا بیس. که این باعث میشه کوئری بعدی به دیتابیس هم کش بشه، در حالی که نمیخوایم از کش استفاده کنیم. چطور میشه این مشکل رو حل کرد؟ چطوری میشه کوئری باقیمانده در کش رو لغو کرد؟

MMSHFE
شنبه 25 مرداد 1393, 09:04 صبح
ببینید شما الان وقتی یک رکورد درج میکنید کش باید Expire بشه چون بیشترین update_time الان فرق کرده. البته به شرط اینکه update_time رو موقع ساخت رکورد با create_time یا timestamp جاری مقداردهی کنید و NULL نباشه.

Muhammad-Ali
شنبه 25 مرداد 1393, 12:47 عصر
update_time که مسلما مقدار داره. زمانی که رکوردی در جدول درج نشده باشه مشکل پیش میاد. CActiveDataProvider میاد اول count رو میگیره برای pagination، بعد رکوردها رو واکشی میکنه. اگر count صفر باشه دیگه رکوردها واکشی نمیشن، بنابراین کوئری بعدی به دیتابیس که میتونه هر جای برنامه باشه ناخواسته مقدارش از روی کش بر میگرده. من میخوام اگر count برابر 0 بود اون یک کوئری بعدی از کش استفاده نکنه.
متوجه منظورم شدید؟

MMSHFE
شنبه 25 مرداد 1393, 12:59 عصر
خوب چرا COUNT(*) رو بعنوان پارامتر cache نمیگذارین. البته باز هم فکر میکنم نباید این کد مشکلی داشته باشه و update_time شما مقدار نداره. یک رکورد دستی درج کنید و update_time رو خالی بگذارین ببینید چی درج میشه و مقدار پیشفرض داره یا نه. اگه داشت که هیچ ولی اگه نداشت کد insert برنامه خودتون یا رفتارهای beforesave و... رو بررسی کنید ببینید update_time مقدار میگیره یا خیر.

Muhammad-Ali
یک شنبه 26 مرداد 1393, 09:22 صبح
فکر میکنم منظور من رو متوجه نشدید. مشکل من با متد CActiveRecordCache (http://www.yiiframework.com/doc/api/1.1/CActiveRecord#cache-detail)هستش.


public CActiveRecord cache(integer $duration, CCacheDependency|ICacheDependency $dependency=NULL, integer $queryCount=1)

وقتی CACtiveDataProvider رو به این صورت به کار می بریم:


CActiveDataProvider(Post::model()->cache($duration, $dependecy, 2) . . .
. . .

یعنی coueryCount رو برابر 2 قرار میدیم، یک کوئری کش برای گرفتن count جهت pagination و یک کوئری کش برای واکشی رکوردها. اگر count برابر 0 باشه. کوئری کش دوم اجرا نمیشه و دستوری بعدی مثل این:


$posts = POST::model()->findAll()

هم از کش استفاده میکنه. در حالی که ما نمیخوایم از کش استفاده بشه. منوجه شدید؟






$queryCount
integer
number of SQL queries that need to be cached after calling this method. Defaults to 1, meaning that the next SQL query will be cached.





البته فکر کنم این کد مشکل رو حل کنه: (بعد از CACtiveDataProvider)


Yii::app()->db->cache()->queryCachingCount = 0

MMSHFE
یک شنبه 26 مرداد 1393, 09:31 صبح
خوب دلیل اینکه 2 گذاشتین چیه؟ همون 1 بگذارین باشه دیگه. Yii بطور خودکار کوئری بعدی رو کش میکنه و موقع واکشی کوئری بعدی، اگه همچنان dependency نقض نشده باشه، یکبار دیگه کش رو تمدید میکنه. شما فقط با همون پارامترهای duration و dependency کار کنید.

Muhammad-Ali
یک شنبه 26 مرداد 1393, 09:39 صبح
دلیل گذاشتن 2:
First param in CActiveDataProvider could be a string with model name or instance of class. So, you may use CActiveRecord::cache() (http://www.yiiframework.com/doc/api/1.1/CActiveRecord#cache-detail) for cache, but you need set third param to 2, because you should cache 2 queries: counting and get data. . . . (http://http://www.yiiframework.com/wiki/233/using-cache-in-cactivedataprovider/)

البته فکر کنم راه حل پیدا شد: (بعد از CACtiveDataProvider)


Yii::app()->db->cache()->queryCachingCount = 0

MMSHFE
یک شنبه 26 مرداد 1393, 09:45 صبح
میشه دقیقاً بگین چه کاری میخواین انجام بدین و طبق چه راهنمایی (لینک بدین) تا اینجا پیش رفتین؟ احساس میکنم یک جای کار رو دارین اشتباه انجام میدین.

Muhammad-Ali
یک شنبه 26 مرداد 1393, 10:50 صبح
میشه دقیقاً بگین چه کاری میخواین انجام بدین و طبق چه راهنمایی (لینک بدین) تا اینجا پیش رفتین؟ احساس میکنم یک جای کار رو دارین اشتباه انجام میدین.
پست قبلی توضیح دادم. که فکر کنم راه رو پیدا شد.

Muhammad-Ali
یک شنبه 26 مرداد 1393, 10:52 صبح
خوب دلیل اینکه 2 گذاشتین چیه؟ همون 1 بگذارین باشه دیگه. Yii بطور خودکار کوئری بعدی رو کش میکنه و موقع واکشی کوئری بعدی، اگه همچنان dependency نقض نشده باشه، یکبار دیگه کش رو تمدید میکنه. شما فقط با همون پارامترهای duration و dependency کار کنید.
مطمئنید؟ من امتحان کردم قبلا جواب نداده! ما میخوایم دو تا کوئری متفاوت کش بشن. یکی برای count یکی هم برای واکشی رکوردها