we extract language rankings from GitHub and Stack Overflow, and combine them for a ranking that attempts to reflect both code (GitHub) and discussion (Stack Overflow) traction. The idea is not to offer a statistically valid representation of current usage, but rather to correlate language discussion and usage in an effort to extract insights into potential future adoption trends.
کتاب Bing Maps V8 Succinctly
At least 80% of all information being collected by enterprises includes geolocation data. The Bing Maps V8 library is a very large collection of JavaScript code that allows web developers to place a map on a webpage, query for data, and manipulate objects on a map, creating a geo-application. In Bing Maps V8 Succinctly, James McCaffrey takes readers through utilizing this library, from creating the simplest application that uses it, to mastering more advanced functions like creating color-gradient legends and custom-styled Infobox objects.
- Getting Started
- Fundamental Techniques
- Working with Data
- Advanced Techniques
4.Visual Studio 2017 15.6 منتشر شد
These are the customer-reported issues addressed in this release:
- Assets File 'c:\xxxxxx\obj\project.assets.json' doesn't have a target for '.NETStandard,Version=v2.0'.
- VS2017 fails to persist settings on first launch if there is another VS instance running from another user.
- Android LLVM libc++ static library STL broken with VS15.6.0.
- Unit tests no longer sorted alphabetically.
- Test explorer tests grouped by class, namespace no longer sorted alphabetically in 15.6.2.
حجم تقریبی بروزرسانی از نسخه 15.6.3 به 15.6.4 برابر 400MB میباشد
PowerShell 7.1 منتشر شد
We’re proud to announce the release of PowerShell 7.1, the latest major update to PowerShell 7. This release includes a number of improvements and fixes that build on top of the PowerShell 7.0 release in March and the recent GA release of .NET 5.
استفاده از Full Text Search بر روی اسناد XML
نحوهی استفاده از Full Text Search بر روی ستونهای XML ایی
برای آزمایش، ابتدا یک جدول جدید را که حاوی ستونی XML ایی است، ایجاد کرده و سپس چند سند XML را که حاوی متونی نسبتا طولانی هستند، در آن ثبت میکنیم. ذکر CONSTRAINT در اینجا جهت دستور ایجاد ایندکس Full Text Search ضروری است.
CREATE TABLE ftsXML( id INT IDENTITY PRIMARY KEY, doc XML NULL CONSTRAINT UQ_FTS_Id UNIQUE(id) ) GO INSERT ftsXML VALUES(' <book> <title>Sample book title 1</title> <author>Vahid</author> <chapter ID="1"> <title>Chapter 1</title> <content> "The quick brown fox jumps over the lazy dog" is an English-language pangram—a phrase that contains all of the letters of the English alphabet. It has been used to test typewriters and computer keyboards, and in other applications involving all of the letters in the English alphabet. Owing to its brevity and coherence, it has become widely known. </content> </chapter> <chapter ID="2"> <title>Chapter 2</title> <content> In publishing and graphic design, lorem ipsum is a placeholder text commonly used to demonstrate the graphic elements of a document or visual presentation. By replacing the distraction of meaningful content with filler text of scrambled Latin it allows viewers to focus on graphical elements such as font, typography, and layout. </content> </chapter> </book> ') INSERT ftsXML VALUES(' <book> <title>Sample book title 2</title> <author>Farid</author> <chapter ID="1"> <title>Chapter 1</title> <content> The original passage began: Neque porro quisquam est qui dolorem ipsum quia dolor sit amet consectetur adipisci velit </content> </chapter> <chapter ID="2"> <title>Chapter 2</title> <content> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </content> </chapter> </book> ') GO
CREATE FULLTEXT CATALOG FT_CATALOG GO CREATE FULLTEXT INDEX ON ftsXML([doc]) KEY INDEX UQ_FTS_Id ON ([FT_CATALOG], FILEGROUP [PRIMARY]) GO
راه اندازی سرویس Full Text Search
البته پیش از ادامهی بحث به کنسول سرویسهای ویندوز مراجعه کرده و مطمئن شوید که سرویس SQL Full-text Filter Daemon Launcher MSSQLSERVER در حال اجرا است. در غیراینصورت با خطای ذیل مواجه خواهید شد:
SQL Server encountered error 0x80070422 while communicating with full-text filter daemon host (FDHost) process.
sp_fulltext_service 'restart_all_fdhosts' go
استفاده از متد Contains
در ادامه، نحوهی ترکیب امکانات Full text search و XQuery را ملاحظه میکنید:
-- استفاده از ایکس کوئری برای جستجو در نتایج حاصل SELECT T.doc.value('(/book/title)[1]', 'varchar(100)') AS title FROM -- استفاده از اف تی اس برای جستجو (SELECT * FROM ftsXML WHERE CONTAINS(doc, '"Quick Brown Fox "')) AS T
خروجی کوئری فوق، Sample book title 1 است.
Full text search امکانات پیشرفتهتری را نیز ارائه میدهد. برای مثال در ردیفهای ثبت شده داریم fox jumps، اما در متن ورودی عبارت جستجو، jumped را وارد کرده و به دنبال نزدیکترین رکورد به آن خواهیم گشت:
SELECT T.doc.value('(/book/title)[1]', 'varchar(100)') AS title FROM (SELECT * FROM ftsXML WHERE CONTAINS(doc, 'FORMSOF (INFLECTIONAL ,"Quick Brown Fox jumped")')) AS T
و یا دو کلمهی نزدیک به هم را میتوان جستجو کرد:
SELECT T.doc.value('(/book/title)[1]', 'varchar(100)') AS title FROM (SELECT * FROM ftsXML WHERE CONTAINS(doc, 'quick NEAR fox')) AS T
نکتهای در مورد متد Contains
هم Full text search و هم XQuery، هر دو دارای متدی به نام Contains هستند اما یکی نمیباشند.
SELECT doc.value('(/book/title)[1]', 'varchar(100)') AS title FROM ftsXML WHERE doc.exist('/book/chapter/content[contains(., "Quick Brown Fox")]') = 1
بنابراین متد contains مرتبط با XQuery یک جستجوی case sensitive را انجام میدهد.
راحت بگویید نه!
در مورد «ما بیکار ننشسته ایم» واقعیت این است که کارهای برنامه نویسی یک سیستم بعد از یک مدت به پایان میرسند و مابقی آن نگهداری است. این فاز نگهداری آنچنان هیجان انگیز نیست. هر روز کار نداره. شاید هفتهای یکی دو تغییر اگر ارجاع شوند. اینطوری مدیر شرکت فکر میکنه داره زیادی حقوق میده. چون شما که به ظاهر کاری نمیکنی. یا به همین دلیل (من دارم بهت حقوق میدم ...) اینقدر تغییرات بیربط رو به سیستم تحمیل میکنه که دست آخر شیرازه سیستم از هم میپاشه. نمونه دیگرش بحث شبکه هست. کار شبکه که تموم شد، مگر مابقی آن چقدر کار دارد؟ حداکثر این است که یک نفر را بگذارند یوزر تعریف کند، دسترسی بدهد. همین. اینجا است که کار کارمندی با رویه کار IT آنچنان جور درنمیاد. ولی همین نگهداری سیستم هم کار هر کسی نیست. این رو هم خیلیها نمیتونند درک کنند.
در کل به نظر من برنامه نویسها نباید خودشون رو درگیر کار کارمندی کنند تا بخواهند با این نوع مسایل سر و کله بزنند و اثبات کنند که وجودشان واقعا ضروری است و اگر در مورد آنها هزینهای انجام میشود، دور ریخته نشده.
برای اینکار 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
متدهای الحاقی و ترکیب کنندههای اعمال غیرهمزمان
متد WhenAll
کار آن ترکیب تعدادی Task است و اجرای آنها. تنها زمانی خاتمه مییابد که کلیهی Taskهای معرفی شده به آن خاتمه یافته باشند. هدف از آن اجرای همزمان و مستقل چندین Task است. برای مثال دریافت چندین فایل به صورت همزمان از اینترنت.
همچنین باید دقت داشت که در اینجا، هر Task کاری به نتایج Taskهای دیگر ندارد و کاملا مستقل اجرا میشود. اگر نیاز است Taskها مستقل اجرا شوند، از همان روش سریالی اجرای Taskها، توسط معرفی هر کدام به کمک await استفاده کنید.
به علاوه اگر در این بین استثنایی وجود داشته باشد، تنها پس از پایان عملیات تمام Taskها بازگشت داده میشود. این استثناء نیز از نوع Aggregate Exception است.
using System.Linq; using System.Threading.Tasks; namespace Async07 { public class EggBoiler { private const int BoilingTimeMs = 200; private static Task boilEgg() { var bolingTask = Task.Run(() => { Task.Delay(BoilingTimeMs); }); return bolingTask; } public async Task BoilEggsSequentialAsync(int count) { for (var i = 0; i < count; i++) { await boilEgg(); } } public async Task BoilEggsSimultaneousAsync(int count) { var tasksList = from egg in new[] { 1, 2, 3, 4, 5 } select boilEgg(); await Task.WhenAll(tasksList); // ... } } }
اما در متد BoilEggsSimultaneousAsync به علت بکارگیری Task.WhenAll پختن تمام تخم مرغهای مدنظر همزمان آغاز میشود و تا پایان عملیات (پخته شدن تمام تخم مرغها) صبر خواهد شد.
متد WhenAny
در حالت استفاده از متد WhenAny، هر کدام از Taskهای در حال پردازش که خاتمه یابند، کل عملیات خاتمه خواهد یافت. فرض کنید نیاز دارید تا دمای کنونی هوای منطقهی خاصی را از چند وب سرویس مختلف دریافت کنید. میتوان در این حالت تمام اینها را توسط WhenAny ترکیب کرد و هر کدام که زودتر خاتمه یابد، عملیات را پایان خواهد داد.
public class Downloader { private Task<string> downloadTask(string url) { return new WebClient().DownloadStringTaskAsync(url); } public async Task<int> GetTemperature() { var sites = new[] { "http://www.site1.com/svc", "http://www.site2.com/svc", "http://www.site3.com/svc", }; var tasksList = from site in sites select downloadTask(site); try { var finishedTask = await Task.WhenAny(tasksList); var result = await finishedTask; } catch (Exception ex) { } // todo: process result, get temperature return 10; // for example. } }
در این حالت اگر نیاز بود وضعیت سایر Taskها، مثلا در صورت شکست آنها، بررسی شوند، میتوان از یکی از دو قطعه کد زیر استفاده کرد:
foreach (var task in tasksList) { var ignored = task.ContinueWith( t => Console.WriteLine(t.Exception), TaskContinuationOptions.OnlyOnFaulted); } // or foreach (var task in tasksList) { var ignored = task.ContinueWith( t => { if (t.IsFaulted) Console.WriteLine(t.Exception); }); }
کاربرد دیگر WhenAny زمانی است که برای مثال میخواهید تعداد زیادی Url را پردازش کنید، اما نمیخواهید برای نمایش اطلاعات، تا پایان عملیات تمامی آنها مانند WhenAll صبر کنید. میخواهید به محض پایان کار یکی از Taskها، عملیات نمایش نتیجهی آنرا انجام دهید:
public async Task ShowTemperatures() { var sites = new[] { "http://www.site1.com/svc", "http://www.site2.com/svc", "http://www.site3.com/svc", }; var tasksList = sites.Select(site => downloadTask(site)).ToList(); while (tasksList.Any()) { try { var tempTask = await Task.WhenAny(tasksList); tasksList.Remove(tempTask); var result = await tempTask; //todo: show result } catch(Exception ex) { } } }
کاربرد سوم WhenAny کنترل تعداد وظایف همزمان است. برای مثال اگر قرار است هزاران تصویر از اینترنت دریافت شوند، نباید تمام وظایف را یکجا راه اندازی کرد. شاید نیاز باشد هربار فقط 15 وظیفهی همزمان عمل کنند و نه بیشتر. در این حالت، مثال قبلی دارای یک حلقهی کنترل کننده tasksList ارائه شده خواهد شد. هر بار تعداد معینی وظیفه به tasksList اضافه و پردازش میشوند و این روند تا پایان کار تعداد Urlها ادامه خواهد یافت (یک Take و Skip است؛ مانند صفحه بندی اطلاعات).
متدهای Run و FromResult
متد Task.Run اضافه شده در دات نت 4.5 به این معنا است که میخواهید Task ایجاد شده بر روی Thread pool اجرا شود. پارامتر آن میتواند یک delegate یا عبارت lambda و یا حتی یک Task باشد. خروجی آن نیز یک Task است و به همین جهت با async و await سی شارپ 5 سازگاری بهتری دارد.
استفاده از Task.Run نسبت به عملیات Threading متداول کارآیی بهتری دارد، زیرا ایجاد Threadهای جدید زمانبر بوده و زمانیکه به صورت خودکار از Thread pool استفاده میشود، تا حد امکان، استفادهی مجدد از تردهای بیکار در حال حاضر، مدنظر است.
متد Task.FromResult کار بازگشت یک Task را از نتایج متدهای مختلف فراهم میکند. فرض کنید یک متد async تعریف کردهاید که خروجی آن Task of T است. در اینجا اگر داخل متد، از یک متد معمولی که یک عدد int را ارائه میدهد استفاده کنیم، با استفاده از Task.FromResult بلافاصله میتوان یک Task of int را بازگشت داد.
متد Delay
پیشتر برای به خواب فرو بردن یک ترد از متد Thread.Sleep استفاده میشد. کار Thread.Sleep بلاک کردن ترد جاری است. در دات نت 4.5، بجای آن باید از Task.Delay استفاده شود که یک مکانیزم غیر قفل کننده را جهت صبر کردن به همراه بازگشت یک Task، ارائه میدهد.
یکی از کاربردهای Delay منهای صبر کردن تا مدت زمانی مشخص، ایجاد مکانیزم timeout است. برای مثال حالت Task.WhenAny را درنظر بگیرید. اگر در اینجا timeout مدنظر ما 3 ثانیه باشد، میتوان یکی از Taskها را Task.Delay با آرگومان مساوی 3000 معرفی کرد. اگر هر کدام از taskهای تعریف شده زودتر از 3 ثانیه پایان یافتند که بسیار خوب؛ در غیر اینصورت Task.Delay معرفی شده کار را تمام میکند.
متد Yield
متد Task.Yield بسیار شبیه به متد قدیمی DoEvents است که از آن برای اجازه دادن به سایر اعمال جهت اجرا، در بین یک عمل طولانی، استفاده میشد.
متد ConfigureAwait
به صورت پیش فرض ادامه یک عملیات همزمان، بر روی ترد ایجاد کنندهی آن اجرا میشود. برای نمونه اگر یک عملیات async در ترد UI آغاز شود، نتیجهی آن نیز در همان ترد UI بازگشت داده میشود. به این ترتیب دیگر نیازی نخواهد بود تا نگرانی در مورد نحوهی دسترسی به مقدار آن توسط عناصر UI داشته باشیم.
اگر به این مساله اهمیت نمیدهید، برای مثال اگر اعمال در حال انجام، کاری به عناصر UI ندارند، از متد ConfigureAwait با پارامتر false بر روی یک task پیش از فراخوانی await بر روی آن، استفاده کنید.
byte [] buffer = new byte[0x1000]; int numRead; while((numRead = await source.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0) { await source.WriteAsync(buffer, 0, numRead).ConfigureAwait(false); }
به صورت خلاصه در سی شارپ 5
- بجای task.Wait قدیمی، از await task برای صبر کردن تا پایان یک task استفاده کنید.
- بجای task.Result جهت دریافت یک نتیجهی یک task از await task کمک بگیرید.
- بجای Task.WaitAll از await Task.WhenAll و بجای Task.WaitAny از await Task.WhenAny استفاده نمائید.
- همچنین Thread.Sleep در اعمال async با await Task.Delay جایگزین شدهاست.
- در اعمال غیرهمزمان همیشه متد ConfigureAwait false را بکار بگیرید، مگر اینکه به Context نهایی آن واقعا نیاز داشته باشید.
و برای ایجاد یک Task جدید از Task.Run یا TaskFactory.StartNew استفاده نمائید.