کتاب C# Code Contracts Succinctly
Developed by Microsoft’s Research in Software Engineering, Code Contracts provide a way to convey code assumptions in your .NET applications. They can take the form of preconditions, postconditions, and state invariants. In C# Code Contracts Succinctly, author Dirk Strauss demonstrates how to use Code Contracts to validate logical correctness in code, how they can be integrated with abstract classes and interfaces, and even how they can be used to make writing documentation less painful.
Recently, Carl Frankin, software developer, musician and presenter on the popular programming podcast DotNet Rocks, released a music album aimed a software developers. The album is called Music to Code By and comprises of 3 x 25 minute long music tracks.
برای اینکار 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);
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
برای مطالعه بیشتر
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
- Azure
- Windows
- Exchange
- SQL
- AWS
- VMWare
- Google Cloud
- Syntax highlighting
- Code snippets
- IntelliSense for cmdlets and more
- Rule-based analysis provided by PowerShell Script Analyzer
- Go to Definition of cmdlets and variables
- Find References of cmdlets and variables
- Document and workspace symbol discovery
- Run selected selection of PowerShell code using F8
- Launch online help for the symbol under the cursor using Ctrl+F1
- Local script debugging
- Extension Terminal support
- PowerShell ISE color theme
نصب PowerShell به چند طریق قابل انجام است که در اینجا میتوانید مشاهده کنید؛ به عنوان مثال برای نصب PowerShell روی macOS تنها کافی است دستور زیر را وارد کنید:
brew install --cask powershell
❯ pwsh PowerShell 7.2.6 Copyright (c) Microsoft Corporation. https://aka.ms/powershell Type 'help' to get help. PS />
With the new Version 7, Entity Framework is moving away from legacy systems and duplications which have accumulated in recent years. As a slim-line new development it will be available for .NET Core, and therefore also WinRT, whilst in addition allowing access to NoSQL databases.This session will show exactly what has changed and how you can benefit from the new possibilities.
نگاهی به ویژگی های جدید 6 #C
The C# language itself has changed little in version 6, the main importance of the release being the introduction of the Roslyn .NET Compiler Platform. However the New features and improvements that have been made to C# are welcome because they are aimed at aiding productivity. Paulo Morgado explains what they are, and how to use them.
ASP.NET Core 1.0 (formerly ASP.NET 5) provides a revamped Web development framework geared towards the requirements of modern Web applications. The new framework, currently in RC1, requires you to learn many new concepts not found in ASP.NET MVC 5. To that end, this article enumerates a few important features that ASP.NET MVC 5 developers should know as they prepare to learn this new framework.
تبدیل عدد به حروف
به طور قطع توابع و کلاسهای تبدیل عدد به حروف، در جعبه ابزار توابع کمکی شما هم پیدا میشوند. روز قبل سعی کردم جهت آزمایش، عدد 3000,000,000,000,000 ریال را با کلاسی که دارم تست کنم و نتیجه overflow یا اصطلاحا ترکیدن سیستم بود! البته اگر مطالب این سایت را دنبال کرده باشید پیشتر در همین راستا مطلبی در مورد نحوهی صحیح بکارگیری توابع تجمعی SQL در این سایت منتشر شده است و جزو الزامات هر سیستمی است (تفاوتی هم نمیکند که به چه زبانی تهیه شده باشد). اگر آنرا رعایت نکردهاید، سیستم شما «روزی» دچار overflow خواهد شد.
در کل این کلاس تبدیل عدد به حروف را به صورت ذیل اصلاح کردم و همچنین دو زبانه است؛ چیزی که کمتر در پیاده سازیهای عمومی به آن توجه شده است:
using System.Collections.Generic;
using System.Linq;
namespace NumberToWordsLib
{
/// <summary>
/// Number to word languages
/// </summary>
public enum Language
{
/// <summary>
/// English Language
/// </summary>
English,
/// <summary>
/// Persian Language
/// </summary>
Persian
}
/// <summary>
/// Digit's groups
/// </summary>
public enum DigitGroup
{
/// <summary>
/// Ones group
/// </summary>
Ones,
/// <summary>
/// Teens group
/// </summary>
Teens,
/// <summary>
/// Tens group
/// </summary>
Tens,
/// <summary>
/// Hundreds group
/// </summary>
Hundreds,
/// <summary>
/// Thousands group
/// </summary>
Thousands
}
/// <summary>
/// Equivalent names of a group
/// </summary>
public class NumberWord
{
/// <summary>
/// Digit's group
/// </summary>
public DigitGroup Group { set; get; }
/// <summary>
/// Number to word language
/// </summary>
public Language Language { set; get; }
/// <summary>
/// Equivalent names
/// </summary>
public IList<string> Names { set; get; }
}
/// <summary>
/// Convert a number into words
/// </summary>
public static class HumanReadableInteger
{
#region Fields (4)
private static readonly IDictionary<Language, string> And = new Dictionary<Language, string>
{
{ Language.English, " " },
{ Language.Persian, " و " }
};
private static readonly IList<NumberWord> NumberWords = new List<NumberWord>
{
new NumberWord { Group= DigitGroup.Ones, Language= Language.English, Names=
new List<string> { string.Empty, "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine" }},
new NumberWord { Group= DigitGroup.Ones, Language= Language.Persian, Names=
new List<string> { string.Empty, "یک", "دو", "سه", "چهار", "پنج", "شش", "هفت", "هشت", "نه" }},
new NumberWord { Group= DigitGroup.Teens, Language= Language.English, Names=
new List<string> { "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen" }},
new NumberWord { Group= DigitGroup.Teens, Language= Language.Persian, Names=
new List<string> { "ده", "یازده", "دوازده", "سیزده", "چهارده", "پانزده", "شانزده", "هفده", "هجده", "نوزده" }},
new NumberWord { Group= DigitGroup.Tens, Language= Language.English, Names=
new List<string> { "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety" }},
new NumberWord { Group= DigitGroup.Tens, Language= Language.Persian, Names=
new List<string> { "بیست", "سی", "چهل", "پنجاه", "شصت", "هفتاد", "هشتاد", "نود" }},
new NumberWord { Group= DigitGroup.Hundreds, Language= Language.English, Names=
new List<string> {string.Empty, "One Hundred", "Two Hundred", "Three Hundred", "Four Hundred",
"Five Hundred", "Six Hundred", "Seven Hundred", "Eight Hundred", "Nine Hundred" }},
new NumberWord { Group= DigitGroup.Hundreds, Language= Language.Persian, Names=
new List<string> {string.Empty, "یکصد", "دویست", "سیصد", "چهارصد", "پانصد", "ششصد", "هفتصد", "هشتصد" , "نهصد" }},
new NumberWord { Group= DigitGroup.Thousands, Language= Language.English, Names=
new List<string> { string.Empty, " Thousand", " Million", " Billion"," Trillion", " Quadrillion", " Quintillion", " Sextillian",
" Septillion", " Octillion", " Nonillion", " Decillion", " Undecillion", " Duodecillion", " Tredecillion",
" Quattuordecillion", " Quindecillion", " Sexdecillion", " Septendecillion", " Octodecillion", " Novemdecillion",
" Vigintillion", " Unvigintillion", " Duovigintillion", " 10^72", " 10^75", " 10^78", " 10^81", " 10^84", " 10^87",
" Vigintinonillion", " 10^93", " 10^96", " Duotrigintillion", " Trestrigintillion" }},
new NumberWord { Group= DigitGroup.Thousands, Language= Language.Persian, Names=
new List<string> { string.Empty, " هزار", " میلیون", " میلیارد"," تریلیون", " Quadrillion", " Quintillion", " Sextillian",
" Septillion", " Octillion", " Nonillion", " Decillion", " Undecillion", " Duodecillion", " Tredecillion",
" Quattuordecillion", " Quindecillion", " Sexdecillion", " Septendecillion", " Octodecillion", " Novemdecillion",
" Vigintillion", " Unvigintillion", " Duovigintillion", " 10^72", " 10^75", " 10^78", " 10^81", " 10^84", " 10^87",
" Vigintinonillion", " 10^93", " 10^96", " Duotrigintillion", " Trestrigintillion" }},
};
private static readonly IDictionary<Language, string> Negative = new Dictionary<Language, string>
{
{ Language.English, "Negative " },
{ Language.Persian, "منهای " }
};
private static readonly IDictionary<Language, string> Zero = new Dictionary<Language, string>
{
{ Language.English, "Zero" },
{ Language.Persian, "صفر" }
};
#endregion Fields
#region Methods (7)
// Public Methods (5)
/// <summary>
/// display a numeric value using the equivalent text
/// </summary>
/// <param name="number">input number</param>
/// <param name="language">local language</param>
/// <returns>the equivalent text</returns>
public static string NumberToText(this int number, Language language)
{
return NumberToText((long)number, language);
}
/// <summary>
/// display a numeric value using the equivalent text
/// </summary>
/// <param name="number">input number</param>
/// <param name="language">local language</param>
/// <returns>the equivalent text</returns>
public static string NumberToText(this uint number, Language language)
{
return NumberToText((long)number, language);
}
/// <summary>
/// display a numeric value using the equivalent text
/// </summary>
/// <param name="number">input number</param>
/// <param name="language">local language</param>
/// <returns>the equivalent text</returns>
public static string NumberToText(this byte number, Language language)
{
return NumberToText((long)number, language);
}
/// <summary>
/// display a numeric value using the equivalent text
/// </summary>
/// <param name="number">input number</param>
/// <param name="language">local language</param>
/// <returns>the equivalent text</returns>
public static string NumberToText(this decimal number, Language language)
{
return NumberToText((long)number, language);
}
/// <summary>
/// display a numeric value using the equivalent text
/// </summary>
/// <param name="number">input number</param>
/// <param name="language">local language</param>
/// <returns>the equivalent text</returns>
public static string NumberToText(this double number, Language language)
{
return NumberToText((long)number, language);
}
/// <summary>
/// display a numeric value using the equivalent text
/// </summary>
/// <param name="number">input number</param>
/// <param name="language">local language</param>
/// <returns>the equivalent text</returns>
public static string NumberToText(this long number, Language language)
{
if (number == 0)
{
return Zero[language];
}
if (number < 0)
{
return Negative[language] + NumberToText(-number, language);
}
return wordify(number, language, string.Empty, 0);
}
// Private Methods (2)
private static string getName(int idx, Language language, DigitGroup group)
{
return NumberWords.Where(x => x.Group == group && x.Language == language).First().Names[idx];
}
private static string wordify(long number, Language language, string leftDigitsText, int thousands)
{
if (number == 0)
{
return leftDigitsText;
}
var wordValue = leftDigitsText;
if (wordValue.Length > 0)
{
wordValue += And[language];
}
if (number < 10)
{
wordValue += getName((int)number, language, DigitGroup.Ones);
}
else if (number < 20)
{
wordValue += getName((int)(number - 10), language, DigitGroup.Teens);
}
else if (number < 100)
{
wordValue += wordify(number % 10, language, getName((int)(number / 10 - 2), language, DigitGroup.Tens), 0);
}
else if (number < 1000)
{
wordValue += wordify(number % 100, language, getName((int)(number / 100), language, DigitGroup.Hundreds), 0);
}
else
{
wordValue += wordify(number % 1000, language, wordify(number / 1000, language, string.Empty, thousands + 1), 0);
}
if (number % 1000 == 0) return wordValue;
return wordValue + getName(thousands, language, DigitGroup.Thousands);
}
#endregion Methods
}
}
دریافت پروژه کامل به همراه Unit tests مرتبط