نظرات مطالب
انجام کارهای زمانبندی شده در برنامه‌های ASP.NET توسط DNT Scheduler
سلام،
ابتدا از مطلب بسیار کاربردیتون تشکر می‌کنم.

سناریوی بنده بدین صورت است که یک task ارسال ایمیل دارم که روزی یکبار به کل کاربرام یک ایمیل رو ارسال می‌کنم. حال از آنجایی که می‌ترسم میل سرور crash کنه و نتونه با سرعت بالا به یکباره همه ایمیل‌ها رو ارسال کنه، بنده می‌خوام بین ارسال هر ایمیل یک تاخیر مثلا 1 ثانیه ای بذارم تا بدین صورت میل سرور زمان تنفس داشته باشه.

به نظر دوستان  آیا اصلا نیاز به ایجاد تاخیر زمانی هست ؟
اگر هست، آیا کد زیر درست است ؟
public override void Run()
{
    if (this.IsShuttingDown || this.Pause)
        return;
 
    var _myService = StructureMapObjectFactory.Container.GetInstance<IMyService>();
    var sendingEmailsData = _myService.GetSendingEmailsData();
 
    if (sendingEmailsData.Count > 0)
    {
        var reader = new StreamReader(SiteCoreManager.SCHEDULE_BODY_PATTERN_FILE_PATH);
        string bodyPattern = reader.ReadToEnd();
 
        foreach (var sendingEmailItem in sendingEmailsData)
        {
            MailSender.Send(bodyPattern, sendingEmailItem   );
 
            // ایجاد تاخیر
            Task.Delay(1000);                   
        }
 
    }
             
}
نظرات اشتراک‌ها
دوراهی انتخاب NHibernate و Entityframework

شما هنوز از ie 8 استفاده می‌کنید؟!

نویسندگان این سایت که قرار نیست برای همه بیان بگن مثلا می‌تونی کوئری‌های لینک رو با تاخیر اجرا کنی. مثلا deferred execution هم وجود داره برای ترکیب چند کوئری با هم. یا این کوئری‌ها همشون پارامتری هستند و مثل رویه‌های ذخیره شده کش میشن. 

اشتراک‌ها
قوانین بقای کسب وکارهای نوپا


یکی از اساسی‌ترین دلیل‌های شکست در کسب و کار‌های نوپا تاخیر در ارائه به مشتریان نهایی است. به شخصه پروژه‌های خیلی ارزشمندی را فقط به خاطر عدم ارائه یا توان ارائه شکست خورده و بعضی از کارهایی بوده که به دلیل تماس با مشتری با وجود ضعف پیاده سازی هنوز زنده است.

قوانین بقای کسب وکارهای نوپا
نظرات مطالب
PHP سریعتر از ASP.NET! افسانه یا واقعیت؟
نمی دونم چرا ولی توی عمل واسه استارت زدن دات نت خیلی دیر میجنبه . حتی بعد از کامپایل و پابلیش یه خورده تاخیر داره ولی یکم که باهاش کار کنی میفته رو دور و خوب میشه !
ولی پی اچ پی همون اول سریعه . شاید بخاط پیچیدگی فریم ورک هست . چرا که entity , linq هم در پرژه استفاده شده است . 
مطالب
مقدمه‌ای بر LINQ بخش اول
کلمه‌ی LINQ مخفف Language Integrated Query یا زبان پرس و جوی یکپارچه می‌باشد. LINQ برای اولین بار در ویژوال استودیوی 2008 و دات نت فریم ورک 3.5 برای پرکردن خلع بین دنیای اشیاء برنامه نویسی (Object Oriented World) و دنیای داده‌ها (Data World) ارائه شد.

چرا LINQ؟ 
در نگاهی کلی، مزایایی که از طریق LINQ حاصل می‌شوند عبارتند از:
• کاهش حجم کدنویسی 
• درک بهتر از عملکرد کد‌های نوشته شده
• پس از یادگیری اصول LINQ به راحتی می‌توانید از این اصول پرس و جو نویسی برای کار بر روی مجموعه داده‌های مختلف استفاده کنید
• کنترل صحت کدهای پرس و جو‌ها در زمان کامپایل ( Compile-Time Type Checking )

اجزای سازنده‌ی LINQ
دو جزء اصلی سازنده‌ی LINQ عبارت است از:
  • Elements عناصر
  • Sequences توالی‌ها
توالی‌ها می‌توانند لیستی از اطلاعات مختلف باشند. هر آیتم در لیست را عنصر می‌گوییم. توالی نمونه‌ای از یک کلاس است که اینترفیس <IEnumarable<T را پیاده سازی کرده باشد. این اینترفیس تضمین می‌کند که توالی قابلیت پیمایش عناصر را دارد.
به آرایه‌ی تعریف شده‌ی زیر دقت کنید:
int[] fibonacci = {0, 1, 1, 2, 3, 5};
متغیر fibonacci در اینجا نشان دهنده‌ی توالی و هر یک از اعداد آرایه، یک عنصر محسوب می‌شوند.
توالی می‌تواند درون حافظه‌ای باشد (In Memory Object) که به آن Local Sequence می‌گویند و یا می‌تواند یک بانک اطلاعاتی SQL Server باشد که به آن Remote Sequence می‌گویند.
در حالت Remote باید اینترفیس <IQuerable<T پیاده سازی شده باشد.
پرس و جو هایی را که بر روی توالی‌های محلی اجرا می‌شوند، اصطلاحا Local Query و یا LINQ-To-Object  نیز می‌نامند.
عملگرهای پرس و جوی  زیادی به شکل متد الحاقی در کلاس System.Linq.Enumerable طراحی شده‌اند. این مجموعه از عملگرهای پرس جو را اصطلاحا Standard Query Operator می‌گویند.
نکته‌ی مهم این است که عملگرهای پرس و جو تغییری را در توالی ورودی نمی‌دهند و نتیجه‌ی خروجی یک مجموعه جدید و یا یک مقدار عددی می‌باشد.

توالی خروجی و مقدار بازگشتی Scalar
در بخش قبل گفتیم که خروجی یک پرس و جو می‌تواند یک مجموعه و یا یک مقدار عددی باشد. در مثال زیر عملگر Count را بر روی مجموعه‌ی fibonacci  اعمال کردیم و عددی که نشان دهنده‌ی تعداد عناصر مجموعه است، بعنوان خروجی بازگردانده شده است.
int[] fibonacci = { 0, 1, 1, 2, 3, 5 };
int numberOfElements = fibonacci.Count();
Console.WriteLine($"{numberOfElements}");
IEnumerable<int> distinictNumbers = fibonacci.Distinct();
Console.WriteLine("Elements in output sequence:");
foreach (var number in distinictNumbers)
{
    Console.WriteLine(number);
}
در کد بالا توسط تابع Distinct، عناصر یکتا را از توالی ورودی استخراج کرده و بازگردانده‌ایم.
خروجی برنامه‌ی فوق به شکل زیر است :
6
Elements in output sequence:
0
1
2
3
5

مفهوم Deffer Execution  (
اجرای به تاخیر افتاده )
عمده‌ی عملگر‌های پرس و جو بلافاصله پس از ایجاد، اجرا نمی‌شوند. این عملگرها در طول اجرای برنامه اجرا خواهند شد (اجرای با تاخیر). به همین خاطر می‌توان بعد از ساخت پرس و جو  تغییرات دلخواهی را به توالی ورودی اعمال کرد.
در کد زیر  قبل از اجرای پرس و جو ، توالی ورودی ویرایش شده :
int[] fibonacci = { 0, 1, 1, 2, 3, 5 };
// ایجاد پرس و جو 
IEnumerable<int> numbersGreaterThanTwoQuery = fibonacci.Where(x => x > 2);
// در این مرحله پرس و جو ایجاد شده ولی هنوز اجرا نشده است
// تغییر عنصر اول توالی
fibonacci[0] = 99;
// حرکت بر روی عناصر توالی باعث اجرای پرس و جو می‌شود
foreach (var number in numbersGreaterThanTwoQuery)
{
   Console.WriteLine(number);
}
پرس و جو تا زمان اجرای حلقه‌ی Foreach اجرا نخواهد شد. خروجی مثال بالا به شکل زیر است :
99
3
5

به غیر از بعضی از عملگرها مثل Count,Min,Last سایر عملگر‌ها بصورت اجرای با تاخیر عمل می‌کنند. عملگری مثل Count باعث اجرای فوری پرس و جو می‌شود.
تعدادی عملگر تبدیل (Conversion Operator) هم وجود دارد که باعث می‌شوند پرس و جو بلافاصله اجرا شود :
• ToList
• ToArray
• ToLookup
• ToDictionary
عملگر‌های فوق پس از اجرا، خروجی را در یک ساختمان داده‌ی جدید باز می‌گردانند.
در کد زیر اصلاح توالی متغیر Fibonacci بعد از اجرای تابع ToArray صورت گرفته است.
int[] fibonacci = { 0, 1, 1, 2, 3, 5 };
// ساخت پرس و جو
IEnumerable<int> numbersGreaterThanTwoQuery = fibonacci.Where(x => x > 2) .ToArray();
// در این مرحله به خاطر عملگر استفاده شده پرس و جو اجرا می‌شود
// تغییر اولین عنصر توالی
fibonacci[0] = 99;
// حرکت بر روی نتیجه
foreach (var number in numbersGreaterThanTwoQuery)
{
   Console.WriteLine(number);
}
خروجی مثال بالا:
3
5
همانطور که می‌بینید عدد 99 در خروجی مشاهده نمی‌شود. علت فراخوانی عملگر ToArray است که بلافاصله باعث اجرای پرس و جو شده و خروجی را باز می‌گرداند . به همین خاطر تغییر عنصر اول توالی ورودی، تاثیری بر روی نتیجه‌ی خروجی ندارد. 
مطالب
ماندگاری با تاخیر در SQL Server 2014
به صورت پیش فرض SQL Server از روش  write-ahead log - WAL استفاده می‌کند. به این معنا که کلیه تغییرات، پیش از commit نهایی باید در لاگ فایل آن نوشته شوند. این مساله با تعداد بالای تراکنش‌ها تا حدودی بر روی سرعت سیستم می‌تواند تاثیرگذار باشد. برای بهبود این وضعیت، در SQL Server 2014 قابلیتی به نام delayed_durability اضافه شده‌است که با فعال سازی آن، کلیه اعمال مرتبط با لاگ‌های تراکنش‌ها به صورت غیرهمزمان انجام می‌شوند. به این ترتیب تراکنش‌ها زودتر از معمول به پایان خواهد رسید؛ با این فرض که نوشته شدن تغییرات در لاگ فایل‌ها، در آینده‌ای محتمل انجام خواهند شد. این مساله به معنای فدا کردن D در ACID است (Atomicity, Consistency, Isolation, Durability). البته باید دقت داشت که رسیدن به ACID کامل هزینه‌بر است و شاید خیلی از اوقات تمام اجزای آن نیازی نباشند یا حتی بتوان با اندکی تخفیف آن‌ها را اعمال کرد؛ مانند D به تاخیر افتاده.
برای اینکار SQL Server از یک بافر 60 کیلوبایتی برای ذخیره سازی اطلاعات لاگ‌هایی که قرار است به صورت غیرهمزمان با تراکنش‌ها نوشته شوند، استفاده می‌کند. هر زمان که این 60KB پر شد، آن‌را flush کرده و ثبت خواهد نمود. به این ترتیب به دو مزیت خواهیم رسید:
- پردازش تراکنش‌ها بدون منتظر شدن جهت commit نهایی در دیسک سخت ادامه خواهند یافت. صبر کمتر به معنای امکان پردازش تراکنش‌های بیشتری در یک سیستم پر ترافیک است.
- با توجه به بافری که از آن صحبت شد، اینبار اعمال Write به صورت یک سری batch اعمال می‌شوند که کارآیی و سرعت بیشتری نسبت به حالت تکی دارند.

اندکی تاریخچه
ایده یک چنین عملی 28 سال قبل توسط Hal Berenson ارائه شده‌است! اوراکل آن‌را در سال 2006 تحت عنوان Asynchronous Commit پیاده سازی کرد و مایکروسافت در سال 2014 آن‌را ارائه داده‌است.


فعال سازی ماندگاری غیرهمزمان در SQL Server

فعال سازی این قابلیت در سطح بانک اطلاعاتی، در سطح یک تراکنش مشخص و یا در سطح رویه‌های ذخیره شده کامپایل شده مخصوص OLTP درون حافظه‌ای، میسر است.
برای فعال سازی ماندگاری با تاخیر در سطح یک دیتابیس، خواهیم داشت:
 ALTER DATABASE dbname SET DELAYED_DURABILITY = DISABLED | ALLOWED | FORCED;


در اینجا اگر ALLOWED را انتخاب کنید، به این معنا است که لاگ کلیه تراکنش‌های مرتبط با این بانک اطلاعاتی به صورت غیرهمزمان نوشته می‌شوند. حالت FORCED نیز دقیقا به همین معنا است با این تفاوت که اگر حالت ALLOWED انتخاب شود، تراکنش‌های ماندگار (آن‌هایی که به صورت دستی DELAYED_DURABILITY را غیرفعال کرده‌اند)، سبب flush کلیه تراکنش‌هایی با ماندگاری به تاخیر افتاده خواهند شد و سپس اجرا می‌شوند. در حالت Forced تنظیم دسترسی DELAYED_DURABILITY = OFF در سطح تراکنش‌ها تاثیری نخواهد داشت؛ اما در حالت ALLOWED این مساله به صورت دستی در سطح یک تراکنش قابل لغو است.
البته باید توجه داشت، صرفنظر از این تنظیمات، یک سری از تراکنش‌ها همیشه ماندگار هستند و بدون تاخیر؛ مانند تراکنش‌های سیستمی، تراکنش‌های بین دو یا چند بانک اطلاعاتی و کلیه تراکنش‌هایی که با FileTable، Change Data Capture و Change Tracking سر و کار دارند.

در سطح تراکنش‌های می‌توان نوشت:
 COMMIT TRANSACTION WITH (DELAYED_DURABILITY = ON);
و یا در رویه‌های ذخیره شده کامپایل شده مخصوص OLTP درون حافظه‌ای خواهیم داشت:
 BEGIN ATOMIC WITH (DELAYED_DURABILITY = ON, ...)

سؤال: آیا فعال سازی DELAYED_DURABILITY بر روی مباحث locking و isolation levels تاثیر دارند؟
پاسخ: خیر. کلیه تنظیمات قفل گذاری‌ها همانند قبل و بر اساس isolation levels تعیین شده، رخ خواهند داد. تنها تفاوت در اینجا است که با فعال سازی DELAYED_DURABILITY، کار commit بدون صبر کردن برای پایان نوشته شدن اطلاعات در لاگ سیستم صورت می‌گیرد. به این ترتیب قفل‌های انجام شده زودتر آزاد خواهند شد.

سؤال: میزان از دست دادن اطلاعات احتمالی در این روش چقدر است؟
در صورتیکه سرور کرش کند یا ری‌استارت شود، حداکثر به اندازه‌ی 60KB اطلاعات را از دست خواهید داد (اندازه‌ی بافری که برای اینکار درنظر گرفته شده‌است). البته عنوان شده‌است که اگر ری‌استارت یا خاموشی سرور، از پیش تعیین شده باشد، ابتدا کلیه لاگ‌های flush نشده، ذخیره شده و سپس ادامه‌ی کار صورت خواهد گرفت؛ ولی زیاد به آن اطمینان نکنید. اما همواره با فراخوانی sys.sp_flush_log، می‌توان به صورت دستی بافر لاگ‌های سیستم را flush کرد.


یک آزمایش

در ادامه قصد داریم یک جدول جدید را در بانک اطلاعاتی آزمایشی testdb2 ایجاد کنیم. سپس یکبار تنظیم DELAYED_DURABILITY = FORCED را انجام داده و 10 هزار رکورد را ثبت می‌کنیم و بار دیگر DELAYED_DURABILITY = DISABLED را تنظیم کرده و همین عملیات را تکرار خواهیم کرد:
CREATE TABLE tblData(
    ID INT IDENTITY(1, 1),
    Data1 VARCHAR(50),
    Data2 INT
);
CREATE CLUSTERED INDEX PK_tblData ON tblData(ID);
CREATE NONCLUSTERED INDEX IX_tblData_Data2 ON tblData(Data2);
 
-------------------------

alter database testdb2 SET DELAYED_DURABILITY = FORCED;

-------------------------

SET NOCOUNT ON
Print 'DELAYED_DURABILITY = FORCED'
DECLARE @counter AS INT = 0
DECLARE @start datetime = getdate()
WHILE (@counter < 10000)
BEGIN
      INSERT INTO tblData (Data1, Data2) VALUES('My Data', @counter)
      SET @counter += 1
END
Print DATEDIFF(ms,@start,getdate());
GO

-------------------------

alter database testdb2 SET DELAYED_DURABILITY = DISABLED;
truncate table tblData;
-------------------------

SET NOCOUNT ON
Print 'DELAYED_DURABILITY = DISABLED'
DECLARE @counter AS INT = 0
DECLARE @start datetime = getdate()
WHILE (@counter < 10000)
BEGIN
      INSERT INTO tblData (Data1, Data2) VALUES('My Data', @counter)
      SET @counter += 1
END
Print DATEDIFF(ms,@start,getdate());
GO

-----------------------
با این خروجی:
 DELAYED_DURABILITY = FORCED
666
DELAYED_DURABILITY = DISABLED
2883
در این آزمایش، سرعت insertها در حالت DELAYED_DURABILITY = FORCED حدود 4 برابر است نسبت به حالت معمولی.


برای مطالعه بیشتر

Control Transaction Durability
SQL Server 2014 Delayed Durability/Lazy Commit
Delayed Durability in SQL Server 2014 – Part 1
Is In-Memory OLTP Always a silver bullet for achieving better transactional speed
Delayed Durability in SQL Server 2014
نظرسنجی‌ها
آیا شما از فناوری Blockchain استفاده می کنید؟
خیر - در حال حاضر، خیر
بله - خیلی استفاده می کنم
بله - مدت کوتاهی است که در حال استفاده هستم
بله - در آینده استفاده خواهم کرد
خیر - نیاز به تحقیقات بیشتری دارم
بله - معمولا کم استفاده می کنم
خیر - آشنایی کاملی ندارم
خیر - اصلا
بازخوردهای دوره
تزریق وابستگی‌ها
- خیر. در حالت setter هم IoC Container (حین استفاده از ابزارهای متداول تزریق وابستگی‌ها) تمام وابستگی‌ها را در حین وهله سازی کلاس ایجاد می‌کند (چه استفاده شوند یا خیر؛ چون اگر اینکار را انجام ندهد استفاده کننده خطای null reference exception را حتما دریافت خواهد کرد. از این جهت که فقط در حالت استفاده از کلاس‌های Lazy است که یک محصور کننده، ارجاع واقعی به شیء را مدیریت می‌کند و به تاخیر می‌اندازد). در حالت به تاخیر افتاده، یک وابستگی فقط زمانی وهله سازی می‌شود که ارجاعی به آن در مسیر منطقی اجرای برنامه وجود داشته باشد؛ در غیراینصورت از وهله سازی آن وابستگی استفاده نشده، صرفنظر خواهد شد.
- برای آزمایش این مساله یک break point را در سازنده کلاس‌های مورد استفاده قرار دهید.