نظرات مطالب
شروع به کار با AngularJS 2.0 و TypeScript - قسمت دهم - کار با فرم‌ها - قسمت اول
به روز رسانی: ارتقاء به نگارش «2.0.0rc.0 » 
جزئیات این مورد و تغییرات مداخل ابتدایی، به همراه فایل main.ts جدید را در نظرات قسمت اول مطالعه بفرمائید. 
نظرات مطالب
شروع به کار با AngularJS 2.0 و TypeScript - قسمت پنجم - بررسی چرخه‌ی حیات کامپوننت‌ها
به روز رسانی: ارتقاء به نگارش «2.0.0rc.0 » 
جزئیات این مورد و تغییرات مداخل ابتدایی، به همراه فایل main.ts جدید را در نظرات قسمت اول مطالعه بفرمائید. 
نظرات مطالب
شروع به کار با AngularJS 2.0 و TypeScript - قسمت سوم - غنی سازی کامپوننت‌ها
به روز رسانی: ارتقاء به نگارش «2.0.0rc.0 » 
جزئیات این مورد و تغییرات مداخل ابتدایی، به همراه فایل main.ts جدید را در نظرات قسمت اول مطالعه بفرمائید. 
نظرات مطالب
شروع به کار با AngularJS 2.0 و TypeScript - قسمت دوم - معرفی کامپوننت‌ها
به روز رسانی: ارتقاء به نگارش «2.0.0rc.0 » 
جزئیات این مورد و تغییرات مداخل ابتدایی، به همراه فایل main.ts جدید را در نظرات قسمت اول مطالعه بفرمائید.
اشتراک‌ها
MASVS یک استاندارد امنیتی مبتنی بر OWASP برای اپلیکیشن‌های موبایل

The Mobile Application Security Verification Standard (MASVS) is a standard for mobile app security


استاندارد امنیتی MASVS شامل موضوعات زیر می‌باشد :

  1. Architecture, Design & Threat Modeling Requirements
  2. Data Storage & Privacy Requirements
  3. Cryptography Requirements
  4. Authentication & Session Management Requirements
  5. Network Communication Requirements
  6. Environmental Interaction Requirements
  7. Code Quality & Build Setting Requirements
  8. Resiliency Against Reverse Engineering Requirements
MASVS یک استاندارد امنیتی مبتنی بر OWASP برای اپلیکیشن‌های موبایل
مطالب
ایجاد نقشه سایت (Site Map) داینامیک
همان طور که می‌دانید نقشه‌ی سایت علاوه بر استفاده از MetaTag‌ها و Url Routing‌ها و ... یکی از نکات اصلی برای سایت شماست که در نتایج گوگل برای جستجو کنندگان نمایش داده شود .

در این مقاله من قصد دارم که به شما چگونگی ایجاد و کار با یک SiteMap  داینامیک را آموزش دهم .
منظور از SiteMap داینامیک این است که به ازای هر مطلبی که شما در سایت تان ایجاد ، ویرایش یا حذف می‌کنید چنانچه دارای صفحه ای در سایت باشد SiteMap تغییر می‌کند .

ساختار یک SiteMap به صورت زیر است :

<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
<loc>Url Page 1</loc>
<lastmod>2014-02-20</lastmod>
<changefreq>always</changefreq>
<priority>1</priority>
  </url>
  <url>
<loc>Url Page 2</loc>
<lastmod>2014-02-20</lastmod>
<changefreq>always</changefreq>
<priority>1</priority>
  </url>
</urlset>
به ازای هر مطلبی که به سایتتان اضافه می‌کنید چنانچه آن مطلب جهت نمایش دارای Url باشد ، باید یک تگ Url  به SiteMap اضافه شود.
تگ loc موجود در تگ url آدرس صفحه را مشخص می‌کند .
تگ lastmod تاریخ اضافه کردن یا آخرین ویرایش را نمایش می‌دهد .
تگ changefreq که دوره‌ی بروز رسانی صفحه را مشخص می‌کند .
تگ priority الویت صفحه را مشخص می‌کند .

که من در کد نویسی تگ changefreq  را always  و تگ priority را  1 قرار دادم.

در فایل ضمیمه یک کلاس به اسم updateSiteMap.cs وجود دارد که تابع آن شامل دو پارامتر ورودی مانند زیر است :

public void UpdateSiteMap(string Addr,string NewOpr)
پارامتر Addr که آدرس صفحه ای است که شما می‌خواهید به SiteMap اضافه شود .
پارامتر NewOpr که می‌تواند شامل یکی از سه مقدار زیر باشد  :add ، edit ، delete

اگر پارامتر NewOpr دارای مقدار add باشد یعنی مقدار موجود در پارامتر Addr را بهSiteMap اضافه کن . یعنی یک تگ url  یه SiteMap اضافه کن .
اگر پارامتر NewOpr دارای مقدار edit باشد یعنی مقدار موجود در تگ <lastmod> را ویرایش کن . یعنی تاریخ آخرین بروزرسانی تغییر می‌کند .
اگر پارامتر NewOpr دارای مقدار delete باشد یعنی تگ url ایی که محتوای تگ loc آن برابر است با مقدار موجود در پارامتر Addr را از SiteMap حذف کن.

این بخش از کد موجود در فایل ضمیمه uupdateSiteMaop.cs  قسمت edit و delete  نقشه‌ی سایت را انجام می‌دهد .
 if (NewOpr != "add")
{
XmlElement xmlElement = xmlDoc.DocumentElement;
if (xmlElement.ChildNodes != null)
{
  foreach (XmlElement myElement in xmlDoc.DocumentElement)
  {
if (myElement.ChildNodes[0].InnerText == Addr)
{
  if (NewOpr != "delete")
myElement.ChildNodes[1].InnerText = DateTime.Now.ToString("yyyy-MM-dd");
  else
myElement.ParentNode.RemoveChild(myElement);
break;
}
  }
}
}

و بخش else دستور بالا قسمت Add  را انجام می‌دهد .یعنی کدهای زیر:
 else
{
string ns="http://www.sitemaps.org/schemas/sitemap/0.9";
XmlNode url = xmlDoc.CreateNode(XmlNodeType.Element, "url",ns );
XmlNode loc = xmlDoc.CreateNode(XmlNodeType.Element, "loc", ns);
XmlNode lastmod = xmlDoc.CreateNode(XmlNodeType.Element, "lastmod", ns);
XmlNode changefreq = xmlDoc.CreateNode(XmlNodeType.Element, "changefreq", ns);
XmlNode priority = xmlDoc.CreateNode(XmlNodeType.Element, "priority", ns);
loc.InnerText = Addr;
lastmod.InnerText = DateTime.Now.ToString("yyyy-MM-dd");
changefreq.InnerText = "always";
priority.InnerText = "1";
url.AppendChild(loc);
url.AppendChild(lastmod);
url.AppendChild(changefreq);
url.AppendChild(priority);
xmlDoc.DocumentElement.AppendChild(url);
}
اگر اطلاعاتی را به جدول اضافه می‌کنید و می‌خواهید Url صفحه‌ی مربوط به آن اطلاعات برای شما در SiteMap اضافه شود  بعد از ذخیره شدن اطلاعات در جدول بلافاصله کد زیر را اضافه می‌کنید :
//
Add Info In Table
//
updateSiteMap updateSiteMap = new updateSiteMap();
updateSiteMap.UpdateSiteMap("Url Page", "add");

برای قسمت ویرایش هم پس از آنکه اطلاعات را ویرایش کردید چنانچه برای آن اطلاعات صفحه ای را در SiteMap درج کرده اید کد زیر را می‌نویسید :
 updateSiteMap updateSiteMap = new updateSiteMap();
updateSiteMap.UpdateSiteMap("Url Page", "edit");

برای قسمت حذف هم اگر شما اطلاعاتی را از جدول حذف می‌کنید چنانچه برای آن اطلاعات صفحه ای در SiteMap درج کرده اید کد زیر را می‌نویسید :
  updateSiteMap updateSiteMap = new updateSiteMap();
updateSiteMap.UpdateSiteMap("Url Page", "delete");

موفق باشید .


 
Files.zip
مطالب دوره‌ها
متدهای توکار استفاده از نوع داده‌ای XML - قسمت دوم
امکان ترکیب داده‌های یک بانک اطلاعاتی رابطه‌ای و XML در SQL Server به کمک یک سری تابع کمکی خاص به نام‌های sql:variable و sql:column پیش بینی شده‌است. sql:variable امکان استفاده از یک متغیر T-SQL را داخل یک XQuery میسر می‌سازد و توسط sql:column می‌توان با یکی از ستون‌های ذکر شده در قسمت select، داخل XQuery کار کرد. در ادامه به مثال‌هایی در این مورد خواهیم پرداخت.

ابتدا جدول xmlTest را به همراه چند رکورد ثبت شده در آن، درنظر بگیرید:
 CREATE TABLE xmlTest
(
 id INT IDENTITY PRIMARY KEY,
 doc XML
)
GO
INSERT xmlTest VALUES('<Person name="Vahid" />')
INSERT xmlTest VALUES('<Person name="Farid" />')
INSERT xmlTest VALUES('<Person name="Mehdi" /><Person name="Hamid" />')
GO

استفاده از متد sql:column

در ادامه می‌خواهیم مقدار ویژگی name رکوردی را که نام آن Vahid است، به همراه id آن ردیف، توسط یک XQuery بازگشت دهیم:
 SELECT doc.query('
for $p in //Person
where $p/@name="Vahid"
return <li>{data($p/@name)} has id = {sql:column("xmlTest.id")}</li>
')
FROM xmlTest
یک sql:column حتما نیاز به یک نام ستون دو قسمتی دارد. قسمت اول آن نام جدول است و قسمت دوم، نام ستون مورد نظر.
در مورد متد data در قسمت قبل بیشتر بحث شد و از آن برای استخراج داده‌ی یک ویژگی در اینجا استفاده شده‌است. عبارات داخل {} نیز پویا بوده و به همراه سایر قسمت‌های ثابت return، ابتدا محاسبه و سپس بازگشت داده می‌شود.
اگر این کوئری را اجرا کنید، ردیف اول آن مساوی عبارت زیر خواهد بود
 <li>Vahid has id = 1</li>
به همراه دو ردیف خالی دیگر در ادامه. این ردیف‌های خالی به علت وجود دو رکورد دیگری است که با شرط where یاد شده تطابق ندارند.
یک روش برای حذف این ردیف‌های خالی استفاده از متد exist است به شکل زیر:
 SELECT doc.query('
for $p in //Person
where $p/@name="Vahid"
return <li>{data($p/@name)} has id = {sql:column("xmlTest.id")}</li>
')
FROM xmlTest
WHERE doc.exist('
for $p in //Person
where $p/@name="Vahid"
return <li>{data($p/@name)} has id = {sql:column("xmlTest.id")}</li>
')=1
در اینجا فقط ردیفی انتخاب خواهد شد که نام ویژگی آن Vahid است.
روش دوم استفاده از یک derived table و بازگشت ردیف‌های غیرخالی است:
 SELECT * FROM
(
 (SELECT doc.query('
 for $p in //Person
 where $p/@name="Vahid"
 return <li>{data($p/@name)} has id = {sql:column("xmlTest.id")}</li>
 ') AS col1
 FROM xmlTest)
) A
WHERE CONVERT(VARCHAR(8000), col1)<>''


استفاده از متد sql:variable

 DECLARE @number INT = 1
SELECT doc.query('
for $p in //Person
where $p/@name="Vahid"
return <li>{data($p/@name)} has number = {sql:variable("@number")}</li>
')
FROM xmlTest
در این مثال نحوه‌ی بکارگیری یک متغیر T-SQL را داخل یک XQuery توسط متد sql:variable ملاحظه می‌کنید.


استفاده از For XML برای دریافت یکباره‌ی تمام ردیف‌های XML

اگر کوئری معمولی ذیل را اجرا کنیم:
 SELECT doc.query('/Person') FROM xmlTest
سه ردیف خروجی را مطابق سه رکوردی که ثبت کردیم، بازگشت می‌دهد.
اما اگر بخواهیم این سه ردیف را با هم ترکیب کرده و تبدیل به یک نتیجه‌ی واحد کنیم، می‌توان از For XML به نحو ذیل استفاده کرد:
 DECLARE @doc XML
SET @doc = (SELECT * FROM xmlTest FOR XML AUTO, ELEMENTS)
SELECT @doc.query('/xmlTest/doc/Person')


بررسی متد xml.nodes

متد xml.nodes اندکی متفاوت است نسبت به تمام متدهایی که تاکنون بررسی کردیم. کار آن تجزیه‌ی محتوای XML ایی به ستون‌ها و سطرها می‌باشد. بسیار شبیه است به متد OpenXML اما کارآیی بهتری دارد.
 DECLARE @doc XML ='
<people>
  <person><name>Vahid</name></person>
  <person><name id="2">Farid</name></person>
  <person><name>Mehdi</name></person>
  <person><name>Hooshang</name><name id="1">Hooshi</name></person>
  <person></person>
</people>
'
در اینجا یک سند XML را درنظر بگیرید که از چندین نود شخص تشکیل شده‌است. اغلب آن‌ها دارای یک name هستند. چهارمین نود، دو نام دارد و آخری بدون نام است.
در ادامه قصد داریم این اطلاعات را تبدیل به ردیف‌هایی کنیم که هر ردیف حاوی یک نام است. اولین سعی احتمالا استفاده از متد value خواهد بود:
 SELECT @doc.value('/people/person/name', 'varchar(50)')
این روش کار نمی‌کند زیرا متد value، بیش از یک مقدار را نمی‌تواند بازگشت دهد. البته می‌توان از متد value به نحو زیر استفاده کرد:
 SELECT @doc.value('(/people/person/name)[1]', 'varchar(50)')
اما حاصل آن دقیقا چیزی نیست که دنبالش هستیم؛ ما دقیقا نیاز به تمام نام‌ها داریم و نه تنها یکی از آن‌ها را.
سعی بعدی استفاده از متد query است:
 SELECT @doc.query('/people/person/name')
در این حالت تمام نام‌ها را بدست می‌آوریم:
 <name>Vahid</name>
<name id="2">Farid</name>
<name>Mehdi</name>
<name>Hooshang</name>
<name id="1">Hooshi</name>
اما این حاصل دو مشکل را به همراه دارد:
الف) خروجی آن XML است.
ب) تمام این‌ها در طی یک ردیف و یک ستون بازگشت داده می‌شوند.

و این خروجی نیز چیزی نیست که برای ما مفید باشد. ما به ازای هر شخص نیاز به یک ردیف جداگانه داریم. اینجا است که متد xml.nodes مفید واقع می‌شود:
 SELECT
tab.col.value('text()[1]', 'varchar(50)') AS name,
tab.col.query('.'),
tab.col.query('..')
from @doc.nodes('/people/person/name') AS tab(col)
خروجی متد xml.nodes یک table valued function است؛ یک جدول را باز می‌گرداند که دقیقا حاوی یک ستون می‌باشد. به همین جهت Alias آن‌را با tab col مشخص کرده‌ایم. tab متناظر است با جدول بازگشت داده شده و col متناظر است با تک ستون این جدول حاصل. این نام‌ها در اینجا مهم نیستند؛ اما ذکر آن‌ها اجباری است.
هر ردیف حاصل از این جدول بازگشت داده شده، یک اشاره‌گر است. به همین جهت نمی‌توان آن‌ها را مستقیما نمایش داد. هر سطر آن، به نودی که با آن مطابق XQuery وارد شده تطابق داشته است، اشاره می‌کند. در اینجا مطابق کوئری نوشته شده، هر ردیف به یک نود name اشاره می‌کند. در ادامه برای استخراج اطلاعات آن می‌توان از متد text استفاده کرد.
اگر قصد داشتید، اطلاعات کامل نود ردیف جاری را مشاهده کنید می‌توان از
 tab.col.query('.'),
استفاده کرد. دات در اینجا به معنای self است. دو دات (نقطه) پشت سرهم به معنای درخواست اطلاعات والد نود می‌باشد.
روش دیگر بدست آوردن مقدار یک نود را در کوئری ذیل مشاهده می‌کنید؛ value دات و data دات. خروجی  value مقدار آن نود است و خروجی data مقدار آن نود با فرمت XML.

 SELECT
tab.col.value('.', 'varchar(50)') AS name,
tab.col.query('data(.)'),
tab.col.query('.'),
tab.col.query('..')
from @doc.nodes('/people/person/name') AS tab(col)

همچنین اگر بخواهیم اطلاعات تنها یک نود خاص را بدست بیاوریم، می‌توان مانند کوئری ذیل عمل کرد:
 SELECT
tab.col.value('name[.="Farid"][1]', 'varchar(50)') AS name,
tab.col.value('name[.="Farid"][1]/@id', 'varchar(50)') AS id,
tab.col.query('.')
from @doc.nodes('/people/person[name="Farid"]') AS tab(col)

در مورد کار با جداول، بجای متغیرهای T-SQL نیز روال کار به همین نحو است:
 DECLARE @tblXML TABLE (
 id INT IDENTITY PRIMARY KEY,
 doc XML
 )

INSERT @tblXML VALUES('<person name="Vahid" />')
INSERT @tblXML VALUES('<person name="Farid" />')
INSERT @tblXML VALUES('<person />')
INSERT @tblXML VALUES(NULL)

SELECT
id,
doc.value('(/person/@name)[1]', 'varchar(50)') AS name
FROM @tblXML
در اینجا یک جدول حاوی ستون XML ایی ایجاد شده‌است. سپس چهار ردیف در آن ثبت شده‌اند. در آخر مقدار ویژگی نام این ردیف‌ها بازگشت داده شده‌است.


نکته : استفاده‌ی وسیع SQL Server از XML برای پردازش کارهای درونی آن

بسیاری از ابزارهایی که در نگارش‌های جدید SQL Server اضافه شده‌اند و یا مورد استفاده قرار می‌گیرند، استفاده‌ی وسیعی از امکانات توکار XML آن دارند. مانند:
Showplan، گراف‌های dead lock، گزارش پروسه‌های بلاک شده، اطلاعات رخدادها، SSIS Jobs، رخدادهای Trace و ...

مثال اول: کدام کوئری‌ها در Plan cache، کارآیی پایینی داشته و table scan را انجام می‌دهند؟

 CREATE PROCEDURE LookForPhysicalOps (@op VARCHAR(30))
AS
SELECT sql.text, qs.EXECUTION_COUNT, qs.*, p.*
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(sql_handle) sql
CROSS APPLY sys.dm_exec_query_plan(plan_handle) p
WHERE query_plan.exist('
declare default element namespace "http://schemas.microsoft.com/sqlserver/2004/07/showplan";
/ShowPlanXML/BatchSequence/Batch/Statements//RelOp/@PhysicalOp[. = sql:variable("@op")]
') = 1
GO

EXECUTE LookForPhysicalOps 'Table Scan'
EXECUTE LookForPhysicalOps 'Clustered Index Scan'
EXECUTE LookForPhysicalOps 'Hash Match'
اطلاعات Query Plan در SQL Server با فرمت XML ارائه می‌شود. در اینجا می‌خواهیم یک سری متغیر مانند Clustered Index Scan و امثال آن‌را از ویژگی PhysicalOp آن کوئری بگیریم. بنابراین از متد  sql:variable کمک گرفته شده‌است.
اگر علاقمند هستید که اصل این اطلاعات را با فرمت XML مشاهده کنید، کوئری نوشته شده را تا پیش از where آن یکبار مستقلا اجرا کنید. ستون آخر آن query_plan نام دارد و حاوی اطلاعات XML ایی است.

مثال دوم:   استخراج اپراتورهای رابطه‌ای (RelOp) از یک Query Plan ذخیره شده

 WITH XMLNAMESPACES(DEFAULT N'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT RelOp.op.value(N'../../@NodeId', N'int') AS ParentOperationID,
RelOp.op.value(N'@NodeId', N'int') AS OperationID,
RelOp.op.value(N'@PhysicalOp', N'varchar(50)') AS PhysicalOperator,
RelOp.op.value(N'@LogicalOp', N'varchar(50)') AS LogicalOperator,
RelOp.op.value(N'@EstimatedTotalSubtreeCost ', N'float') AS EstimatedCost,
RelOp.op.value(N'@EstimateIO', N'float') AS EstimatedIO,
RelOp.op.value(N'@EstimateCPU', N'float') AS EstimatedCPU,
RelOp.op.value(N'@EstimateRows', N'float') AS EstimatedRows,
cp.plan_handle AS PlanHandle,
st.TEXT AS QueryText,
qp.query_plan AS QueryPlan,
cp.cacheobjtype AS CacheObjectType,
cp.objtype AS ObjectType
FROM sys.dm_exec_cached_plans cp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) qp
CROSS APPLY qp.query_plan.nodes(N'//RelOp') RelOp(op)
در اینجا کار کردن با WITH XMLNAMESPACES در حین استفاده از متد xml.nodes ساده‌تر است؛ بجای قرار دادن فضای نام در تمام کوئری‌های نوشته شده.


بررسی متد xml.modify

تا اینجا تمام کارهایی که صورت گرفت و نکاتی که بررسی شدند، به مباحث select اختصاص داشتند. اما insert، delete و یا update قسمتی از یک سند XML بررسی نشدند. برای این منظور باید از متد xml.modify استفاده کرد. از آن در عبارات update و یا set کمک گرفته شده و ورودی آن نباید نال باشد. در ادامه در طی مثال‌هایی این موارد را بررسی خواهیم کرد.
ابتدا فرض کنید که سند XML ما چنین شکلی را دارا است:
DECLARE @doc XML = '
<Invoice>
<InvoiceId>100</InvoiceId>
<CustomerName>Vahid</CustomerName>
<LineItems>
<LineItem>
<Sku>134</Sku>
<Quantity>10</Quantity>
<Description>Item 1</Description>
<UnitPrice>9.5</UnitPrice>
</LineItem>
<LineItem>
<Sku>150</Sku>
<Quantity>5</Quantity>
<Description>Item 2</Description>
<UnitPrice>1.5</UnitPrice>
</LineItem>
</LineItems>
</Invoice>
'
در ادامه قصد داریم یک نود جدید را پس از CustomerName اضافه کنیم.
 SET @doc.modify('
insert <InvoiceInfo><InvoiceDate>2014-02-10</InvoiceDate></InvoiceInfo>
after /Invoice[1]/CustomerName[1]
')

SELECT @doc
اینکار را با استفاده از دستور insert، به نحو فوق می‌توان انجام داد. از عبارت Set و متغیر doc مقدار دهی شده، کار شروع شده و سپس نود جدیدی پس از (after) اولین نود CustomerName موجود insert می‌شود. Select بعدی نتیجه را نمایش خواهد داد.
<Invoice>
  <InvoiceId>100</InvoiceId>
  <CustomerName>Vahid</CustomerName>
  <InvoiceInfo>
        <InvoiceDate>2014-02-10</InvoiceDate>
  </InvoiceInfo>
  <LineItems>
...

در SQL Server 2008 به بعد، امکان استفاده از متغیرهای T-SQL نیز در اینجا مجاز شده‌است:
 SET @x.modify('insert sql:variable("@x") into /doc[1]')
بنابراین اگر نیاز به تعریف متغیری در اینجا داشتید از جمع زدن رشته‌ها استفاده نکنید. حتما نیاز است متغیر تعریف شود و گرنه باخطای ذیل متوقف خواهید شد:
 The argument 1 of the XML data type method "modify" must be a string literal.


افزودن ویژگی‌های جدید به یک سند XML توسط متد xml.modify

اگر بخواهیم یک ویژگی (attribute) جدید را به نود خاصی اضافه کنیم می‌توان به نحو ذیل عمل کرد:
 SET @doc.modify('
insert attribute status{"backorder"}
into /Invoice[1]
')

SELECT @doc
که خروجی دو سطر ابتدایی آن پس از اضافه شدن ویژگی status با مقدار backorder به نحو ذیل است:
 <Invoice status="backorder">
  <InvoiceId>100</InvoiceId>
....


حذف نودهای یک سند XML توسط متد xml.modify

اگر بخواهیم تمام LineItemها را حذف کنیم می‌توان نوشت:
 SET @doc.modify('delete /Invoice/LineItems/LineItem')
SELECT @doc
با این خروجی:
 <Invoice status="backorder">
  <InvoiceId>100</InvoiceId>
  <CustomerName>Vahid</CustomerName>
  <InvoiceInfo>
      <InvoiceDate>2014-02-10</InvoiceDate>
  </InvoiceInfo>
  <LineItems />
</Invoice>


به روز رسانی نودهای یک سند XML توسط متد xml.modify

اگر نیاز باشد تا مقدار یک نود را تغییر دهیم می‌توان از replace value of استفاده کرد:
 SET @doc.modify('replace value of
  /Invoice[1]/CustomerName[1]/text()[1]
  with "Farid"
')
SELECT @doc
با خروجی ذیل که در آن نام اولین مشتری با مقدار Farid جایگزین شده است:
 <Invoice status="backorder">
  <InvoiceId>100</InvoiceId>
  <CustomerName>Farid</CustomerName>
  <InvoiceInfo>
       <InvoiceDate>2014-02-10</InvoiceDate>
  </InvoiceInfo>
  <LineItems />
</Invoice>
replace value of فقط با یک نود کار می‌کند و همچنین، فقط مقدار آن نود را تغییر می‌دهد. به همین جهت از متد text استفاده شده‌است. اگر از text استفاده نشود با خطای ذیل متوقف خواهیم شد:
 The target of 'replace value of' must be a non-metadata attribute or an element with simple typed content.


به روز رسانی نودهای خالی توسط متد xml.modify

باید دقت داشت، نودهای خالی (بدون مقدار)، مانند LineItems پس از delete کلیه اعضای آن در مثال قبل، قابل replace نیستند و باید مقادیر جدید را در آن‌ها insert کرد. یک مثال:

 DECLARE @tblTest AS TABLE (xmlField XML)

INSERT INTO @tblTest(xmlField)
VALUES
 (
'<Sample>
   <Node1>Value1</Node1>
   <Node2>Value2</Node2>
   <Node3/>
</Sample>'
)
 
DECLARE @newValue VARCHAR(50) = 'NewValue'

UPDATE @tblTest
SET xmlField.modify(
'insert text{sql:variable("@newValue")} into
  (/Sample/Node3)[1] [not(text())]'
)

SELECT xmlField.value('(/Sample/Node3)[1]','varchar(50)') FROM @tblTest
در این مثال اگر از replace value of برای مقدار دهی نود سوم استفاده می‌شد:
 UPDATE @tblTest
SET xmlField.modify(
'replace value of (/Sample/Node3/text())[1]
  with sql:variable("@newValue")'
)
تغییری را پس از اعمال دستورات مشاهده نمی‌کردید؛ زیرا این المان ()text ایی را برای replace شدن ندارد.
مطالب
OpenCVSharp #1
معرفی OpenCV

پردازش تصاویر علمی است برای پیاده سازی الگوریتم‌های مختلفی بر روی تصاویر دیجیتال؛ برای مثال تشخیص خودکار شماره‌ی پلاک خودروهای وارد شده‌ی به محدوده‌ی طرح ترافیک، تا تشخیص چهره‌ی افراد، در گوشی‌های همراه. پردازش تصاویر، در صنایع مختلف، علوم پزشکی و همچنین نظامی، کاربردهای بسیاری دارند.
برای انجام این کار، کتابخانه‌های بسیار زیادی طراحی شده‌اند؛ اما در این بین OpenCV جایگاه خاصی دارد. این کتابخانه‌ی بسیار مشهور سورس باز، جهت پردازش تصاویر در سیستم عامل‌های مختلفی مانند Windows, Mac, Linux, Android و iOS بکار می‌رود.


محصور کننده‌های OpenCV مخصوص دات نت

تا امروز محصور کننده‌های زیادی جهت استفاده‌ی از کتابخانه‌ی OpenCV در دات نت طراحی شده‌اند که تعدادی از مهم‌ترین‌های آن‌ها به شرح زیر هستند:

الف) Emgu CV
این کتابخانه، یکی از مشهورترین محصور کننده‌های OpenCV است و دارای مجوزی دوگانه می‌باشد. برای کارهای سورس باز، مجوز GPL دارد (یعنی باید کارتان را سورس باز کنید) و برای کارهای تجاری باید مجوز آن‌را بخرید. البته باید توجه داشت که مجوز کتابخانه‌ی اصلی OpenCV از نوع BSD است و این محدودیت‌ها را ندارد.

ب) OpenCvSharp
کتابخانه‌ی OpenCvSharp دارای مجوز BSD است (همانند کتابخانه‌ی اصلی OpenCV) و محدودیتی برای استفاده ندارد. هر دو نوع مدل برنامه نویسی OpenCV را که شامل متدهای C و ++C آن‌است، پشتیبانی می‌کند و در طراحی آن سعی شده‌است که بیشترین نزدیکی به طراحی اصلی OpenCV وجود داشته باشد. همچنین این کتابخانه چندسکویی بوده و با Mono لینوکسی نیز سازگار است و از دات نت 2 به بعد را نیز پشتیبانی می‌کند. جامعه‌ی کاربری آن فعال است و مدام به روز می‌شود.

ج) SharperCV
دیگر نگهداری نمی‌شود.

د) OpenCVDotNet 
آخرین تاریخ به روز رسانی آن سال 2007 است.

ه) DirectCV
آخرین تاریخ به روز رسانی آن سال 2011 است.


در این بین یکی از بهترین انتخاب‌ها، کتابخانه‌ی OpenCvSharp ژاپنی است. مجوز استفاده‌ی از آن محدود نیست. به روز رسانی مرتب و منظمی دارد و API آن طوری طراحی شده‌است که به سادگی بتوانید مثال‌های C و ++C کتابخانه‌ی OpenCV را تبدیل به معادل‌های #C کنید.


نصب OpenCvSharp

برای نصب کتابخانه‌ی OpenCvSharp می‌توان از بسته‌های نیوگت آن کمک گرفت. این کتابخانه به همراه دو بسته‌ی نیوگت ارائه می‌شود.
اگر فرمان ذیل را صادر کنید
 PM> Install-Package OpenCvSharp-AnyCPU
علاوه بر اسمبلی‌های دات نتی OpenCVSharp، کتابخانه‌ی native مربوط به OpenCV سازگار با نگارش ارائه شده را نیز دریافت خواهید کرد.
و اگر دستور ذیل را اجرا کنید:
 PM> Install-Package OpenCvSharp-WithoutDll
به این معنا است که تنها اسمبلی‌های دات نتی OpenCVSharp را دریافت می‌کنید. در این حالت نیاز است به سایت OpenCV مراجعه و بسته‌های کامپایل شده‌ی آن‌را دریافت کنید. سپس فایل‌های dll موجود در پوشه‌ی opencv\build\x64\vc12\bin را برای مثال به پوشه‌ی bin پروژه‌ی خود کپی نمائید.

روش توصیه شده‌ی در اینجا، همان نصب بسته‌ی نیوگت OpenCvSharp-AnyCPU است. به این ترتیب نگارش‌های X86 و X64 کتابخانه‌ی OpenCV سازگار با OpenCvSharp را نیز دریافت خواهید کرد.


نکته‌ای در مورد ارائه‌ی نهایی پروژه‌های مبتنی بر OpenCV

OpenCV یک کتابخانه‌ی native ویندوز است و دات نتی نیست . بنابراین DLL‌های آن باید بسته به معماری CPU جاری، انتخاب شوند. یعنی اگر برنامه‌ی دات نتی خود را در حالت Any CPU کامپایل می‌کنید، این برنامه در یک سیستم 64 بیتی، 64 بیتی رفتار می‌کند و در یک سیستم 32 بیتی، 32 بیتی. بنابراین باید دقت داشت که اگر سیستم جاری 64 بیتی است و می‌خواهید از اسمبلی‌های X86 مربوط به OpenCV استفاده کنید، برنامه با پیام استثنای یافت نشدن OpenCV و BadImageFormatException کرش خواهد کرد. بسته‌ی نیوگت OpenCvSharp-AnyCPU  شامل هر دو معماری X86 و X64 است و هر دو سری DLLهای OpenCV را به همراه دارد.
همچنین OpenCV تحت ویندوز، توسط کامپایلر ویژوال ++C، کامپایل شده‌است. به همین جهت در این حالت، علاوه بر نصب دات نت، نیاز است VC++ redistributable packages را نیز بر روی کامپیوتر کلاینت نصب کرد.
پس از نصب بسته‌ی نیوگت OpenCvSharp-AnyCPU اگر به پوشه‌ی bin برنامه‌ی خود مراجعه کنید، پوشه‌ی جدید dll را نیز می‌توان مشاهده کرد. داخل این پوشه، دو پوشه‌ی X86 و X64 وجود دارند که حاوی DLLهای اصلی OpenCV می‌باشند. در این پوشه‌ها اگر برای مثال فایلی به نام msvcp120.dll را یافتید، یعنی این نگارش از OpenCV نیاز به بسته‌های مخصوص VC++ 12 دارد.

رعایت این دو نکته بسیار مهم است؛ در غیر اینصورت برنامه‌ی شما آغاز نخواهد شد.


اولین برنامه‌ی OpenCVSharp


پس از نصب بسته‌ی نیوگت OpenCvSharp-AnyCPU، مقدمات نصب OpenCV به پایان می‌رسد. در ادامه یک برنامه‌ی کنسول جدید را ایجاد کرده و کدهای ذیل را به آن اضافه کنید:
using OpenCvSharp;
 
namespace OpenCVSharpSample01
{
    class Program
    {
        static void Main(string[] args)
        {
            var img = Cv.CreateImage(new CvSize(128, 128), BitDepth.U8, 1);
 
            for (var y = 0; y < img.Height; y++)
            {
                for (var x = 0; x < img.Width; x++)
                {
                    Cv.Set2D(img, y, x, x + y);
                }
            }
 
            Cv.NamedWindow("window");
            Cv.ShowImage("window", img);
            Cv.WaitKey();
            Cv.DestroyWindow("window");
 
            Cv.ReleaseImage(img);
        }
    }
}
این خروجی را دریافت خواهید کرد:


در این مثال یک تصویر 128*128 ایجاد شده و سپس با گرادیانی از رنگ خاکستری پر می‌شود. در ادامه یک پنجره‌ی native مخصوص OpenCV ایجاد شده و این تصویر در آن نمایش داده می‌شود.


کدهای کامل این مثال را از اینجا می‌توانید دریافت کنید.
مطالب
چرا TypeScript؟
زبان TypeScript به عنوان superset زبان JavaScript ارائه شده‌است و هدف آن، strong typing و ارائه‌ی قابلیت‌های پیشرفته‌ی زبان‌های شیءگرا، جهت نوشتن برنامه‌های کلاینت و سرور، با کمترین میزان خطاها است. زبان TypeScript چندسکویی و سورس باز است و در نهایت به نگارشی از JavaScript کامپایل می‌شود که با تمام مرورگرهای فعلی سازگاری دارد و یا در سمت سرور بدون مشکلی توسط NodeJS قابل درک است.
- TypeScript زبان توصیه شده‌ی توسعه‌ی برنامه‌های AngularJS 2 است و همچنین با سایر کتابخانه‌های معروف جاوا اسکریپتی مانند ReactJS و jQuery نیز سازگاری دارد. بنابراین اگر قصد دارید به AngularJS 2 مهاجرت کنید، اکنون فرصت خوبی است تا زبان TypeScript را نیز بیاموزید. همچنین WinJS نیز با TypeScript نوشته شده‌است.
- superset زبان JavaScript بودن به این معنا است که تمام کدهای جاوا اسکریپتی موجود، به عنوان کد معتبر TypeScript نیز شناخته می‌شوند و همین مساله مهاجرت به آن‌را ساده‌تر می‌کند. زبان‌های دیگری مانند Dart و یا CoffeeScript ، نسبت به JavaScript بسیار متفاوت به نظر می‌رسند؛ اما Syntax زبان TypeScript شباهت بسیار زیادی به جاوا اسکریپت و خصوصا ES 6 دارد. در اینجا تنها کافی است پسوند فایل‌های js را به ts تغییر دهید و از آن‌ها به عنوان کدهای معتبر TypeScript استفاده کنید.
- strong typing و معرفی نوع‌ها، کدهای نهایی نوشته شده را امن‌تر می‌کنند. به این ترتیب کامپایلر، پیش از اینکه کدهای شما در زمان اجرا به خطا بر بخورند، در زمان کامپایل، مشکلات موجود را گوشزد می‌کند. همچنین وجود نوع‌ها، سرعت توسعه را با بهبود ابزارهای مرتبط با برنامه نویسی، افزایش می‌دهند؛ از این جهت که مفهوم مهمی مانند Intellisense، با وجود نوع‌ها، پیشنهادهای بهتر و دقیق‌تری را ارائه می‌دهد. همچنین ابزارهای Refactoring نیز در صورت وجود نوع‌ها بهتر و دقیق‌تر عمل می‌کنند. این موارد مهم‌ترین دلایل طراحی TypeScript جهت توسعه و نگهداری برنامه‌های بزرگ نوشته شده‌ی با JavaScript هستند.
- Syntax زبان TypeScript به شدت الهام گرفته شده از زبان سی‌شارپ است. به همین جهت اگر با این زبان آشنایی دارید، درک مفاهیم TypeScript برایتان بسیار ساده خواهد بود.
- بهترین قسمت TypeScript، کامپایل شدن آن به ES 5 است (به این عملیات Transpile هم می‌گویند). در زبان TypeScript به تمام امکانات پیشرفته‌ی ES 6 مانند کلاس‌ها و ماژول‌ها دسترسی دارید، اما کد نهایی را که تولید می‌کند، می‌تواند ES 5 ایی باشد که هم اکنون تمام مرورگرهای عمده آن‌را پشتیبانی می‌کنند. با تنظیمات کامپایلر TypeScript، امکان تولید کدهای ES 3 تا ES 5 و همچنین ES 6 نیز وجود دارد. نمونه‌ی آنلاین این ترجمه را در TypeScript playground می‌توانید مشاهده کنید.
- TypeScript چندسکویی است. امکانات و کامپایلر این زبان، برای ویندوز، مک و لینوکس طراحی شده‌اند.
- TypeScript سورس باز است. طراحان اصلی آن، همان طراحان زبان سی‌شارپ در مایکروسافت هستند و هم اکنون این زبان به صورت سورس باز توسط این شرکت توسعه داده شده و در GitHub نگهداری می‌شود.


آماده سازی محیط‌های کار با TypeScript

برای کار با TypeScript، یک ادیتور متنی ساده، به همراه کامپایلر آن کفایت می‌کند. اما همانطور که عنوان شد، یکی از مهم‌ترین دلایل وجودی TypeScript، بهبود ابزارهای برنامه نویسی مرتبط با JavaScript است و اگر قرار باشد صرفا از یک ادیتور متنی ساده استفاده شود، فلسفه‌ی وجودی آن زیر سؤال می‌رود.

نصب TypeScript در ویژوال استودیو

در نگارش‌های جدید ویژوال استودیو، از VS 2013 Update 2 به بعد، قسمت ویژه‌ی TypeScript نیز قابل مشاهده‌است. البته این قسمت با به روز رسانی‌های TypeScript، نیاز به به روز رسانی دارد. به همین جهت به سایت رسمی آن مراجعه کرده و بسته‌های جدید مخصوص VS 2013 و یا 2015 آن‌را دریافت و نصب کنید.


همچنین افزونه‌ی Web Essentials نیز امکانات بیشتری را جهت کار با TypeScript به همراه دارد و امکان مشاهده‌ی خروجی جاوا اسکریپت تولیدی را در حین کار با فایل TypeScript فعلی میسر می‌کند. در سمت چپ صفحه TypeScript را خواهید نوشت و در سمت راست، خروجی JavaScript نهایی را بلافاصله مشاهده می‌کنید.


تصویر فوق مربوط به VS 2015 است. همچنین گزینه‌ی افزودن یک فایل و آیتم جدید نیز امکان افزودن فایل‌های TS را به همراه دارد.


نصب و تنظیم TypeScript در ویژوال استودیو کد

ویژوال استودیو کد، نگارش رایگان، سورس باز و چندسکویی ویژوال استودیو است که بر روی ویندوز، مک و لینوکس قابل اجرا است. ویژوال استودیو کد نیز به همراه پشتیبانی بسیار خوبی از TypeScript است، تا حدی که تمام ارائه‌های معرفی Anugular 2 توسط تیم مربوطه‌ی آن از گوگل، توسط ویژوال استودیو کد و یکپارچگی آن با TypeScript انجام شدند.


ویژوال استودیو کد بر مبنای فولدرها کار می‌کند و با گشودن یک پوشه در آن (با کلیک بر روی دکمه‌ی open folder آن)، امکان کار کردن با آن پوشه و فایل‌های موجود در آن را خواهیم یافت.
نکته‌ی مهم اینجا است که پس از نصب VS Code، برای فایل‌های با پسوند ts بلافاصله Intellisense مرتبط نیز مهیا است و نیاز به هیچگونه تنظیم اضافه‌تری ندارد. همچنین قابلیت‌های type safety این زبان نیز در این ادیتور به نحو واضحی مشخص هستند:


در ادامه ابتدا یک پوشه‌ی جدید خالی را ایجاد کنید و سپس این پوشه را در VS Code باز نمائید (از طریق منوی فایل، گزینه‌ی گشودن پوشه). سپس ماوس را بر روی نام این پوشه حرکت دهید:


همانطور که مشاهده می‌کنید، دکمه‌ی new file ظاهر می‌شود. در اینجا می‌توانید فایل جدیدی را به نام test.ts اضافه کنید.
در ادامه با فشردن دکمه‌های ctrl+shift+p، امکان انتخاب یک task runner را جهت کامپایل فایل‌های ts خواهیم داشت:


در اینجا ابتدا عبارت task< را وارد کنید و سپس از منوی باز شده، گزینه‌ی rub build task را انتخاب کنید:


پس از آن، در بالای صفحه مشاهده خواهید کرد که عنوان شده: «هنوز هیچ task runner ایی برای اینکار تنظیم نشده‌است»


برای این منظور بر روی دکمه‌ی configure task runner تصویر فوق که با رنگ آبی مشخص شده‌است، کلیک کنید. به این ترتیب یک فایل جدید به نام task.json ایجاد می‌شود که در پوشه‌ای به نام vscode. در ریشه‌ی پروژه (یا همان پوشه‌ی جاری) قرار می‌گیرد:


فایل task.json دارای تعاریفی است که کامپایلر TypeScript یا همان tsc را فعال می‌کند:
{
"version": "0.1.0",

// The command is tsc. Assumes that tsc has been installed using npm install -g typescript
"command": "tsc",

// The command is a shell script
"isShellCommand": true,

// Show the output window only if unrecognized errors occur.
"showOutput": "silent",

// args is the HelloWorld program to compile.
"args": ["HelloWorld.ts"],

// use the standard tsc problem matcher to find compile problems
// in the output.
"problemMatcher": "$tsc"
}
محتوای پیش فرض و ابتدایی این فایل را در قطعه کد فوق مشاهده می‌کنید. این فایل json را جهت تنظیمات کامپایلر TypeScript پروژه‌ی جاری، ویرایش خواهیم کرد. در این فایل دکمه‌ی ctrl+space را بفشارید. بلافاصله منوی تکمیل کننده‌ی این فایل ظاهر می‌شود. از ترکیب ctrl+space در قسمت‌های مختلف این فایل جهت دریافت توصیه‌های بیشتری نیز می‌توان استفاده کرد.
در اینجا قسمتی که نیاز به تنظیم دارد، خاصیت args است. مقادیر آن، پارامترهایی هستند که به کامپایلر typescript ارسال می‌شوند. برای نمونه آن‌را به صورت ذیل تغییر دهید:
"args": [
         "--target", "ES5",
         "--outdir", "js",
         "--sourceMap",
         "--watch",
         "test.ts"
    ],
پارامتر و سوئیچ target مشخص می‌کند که خروجی تولیدی باید با فرمت ES 5 باشد. همچنین فایل‌های js تولیدی را در پوشه‌ی js در ریشه‌ی پروژه یا پوشه‌ی جاری قرار دهد. پارامتر sourceMap مشخص می‌کند که علاوه بر فایل‌های js، فایل‌های map که بیانگر نگاشت بین فایل‌های ts و js هستند نیز تولید شوند. این فایل‌ها برای دیباگ برنامه بسیار مفید هستند. پارامتر watch، کلیه‌ی تغییرات پوشه‌ی جاری را تحت نظر قرار داده و به صورت خودکار کار کامپایل را انجام می‌دهد. در آخر نیز فایل و یا فایل‌های ts مدنظر ذکر می‌شوند.
برای اجرای کامپایلر، ابتدا از منوی view گزینه‌ی toggle output را انتخاب کنید تا بتوان خروجی نهایی کامپایلر را مشاهده کرد. سپس گزینه‌ی view->command pallet و اجرا tasks< را انتخاب کنید. در ادامه همانند مرحله‌ی قبل، یعنی گزینه‌ی run build task را اجرا کنید (که خلاصه‌ی این عملیات ctrl+shift+B است).

به این ترتیب پوشه‌ی js که در خاصیت args مشخص کردیم، تولید می‌شود:


البته این خطا هم در قسمت output نمایش داده می‌شود:
 error TS5023: Unknown option 'watch'
Use the '--help' flag to see options.

علت اینجا است که در تنظیمات فوق، خاصیت command به tsc تنظیم شده‌است و همانطور که در کامنت آن عنوان شده‌است، کامپایلر typescript را از طریق دستور npm install -g typescript دریافت می‌کند و نیازی به ذکر مسیر آن در اینجا نیست. بنابراین لازم است تا با npm و نصب typescript از طریق آن آشنا شد و به این ترتیب کامپایلر آن‌را به روز کرد تا دستور watch را شناسایی کند.


نصب TypeScript از طریق npm

همانطور که عنوان شد، TypeScript چندسکویی است و این مورد را از طریق npm یا NodeJS package manager انجام می‌دهد. برای این منظور به آدرس https://nodejs.org/en   مراجعه کرده و فایل نصاب آن‌را مخصوص سیستم عامل خود دریافت و سپس نصب کنید. Node.js یک runtime سمت سرور اجرای برنامه‌های جاوا اسکریپتی است. از آنجائیکه TypeScript در نهایت به JavaScript تبدیل می‌شود، استفاده از node.js انتخاب مناسبی جهت اجرا و توزیع آن در تمام سیستم عامل‌ها بوده‌است.
پس از نصب node.js، از package manager آن که npm نام دارد، جهت نصب TypeScript استفاده می‌شود. چون node.js به Path و مسیرهای اصلی ویندوز اضافه می‌شود، تنها کافی است دستور npm install -g typescript را در خط فرمان صادر کنید. در اینجا سوئیچ g به معنای global و دسترسی عمومی است.


همانطور که در این تصویر مشخص است، پس از صدور دستور نصب TypeScript، نگارش 1.8.9 آن نصب شده‌است. اما زمانیکه کامپایلر tsc را با پارامتر version اجرا می‌کنیم، شماره نگارش قدیمی 1.0.3.0 را نمایش می‌دهد. برای رفع این مشکل به مسیر C:\Program Files (x86)\Microsoft SDKs\TypeScript مراجعه کرده و پوشه‌ی 1.0 را به 1.0-old تغییر نام دهید.


اکنون اگر مجددا بررسی کنیم، نگارش صحیح قابل مشاهده است:


پس از این تغییرات اگر مجددا به VS Code باز گردیم و ctrl+shift+B را صادر کنیم (جهت اجرای مجدد task runner و اجرای tsc تنظیم شده) ، پیام ذیل مشاهده می‌شود:
 15:33:52 - Compilation complete. Watching for file changes.
به این معنا که اینبار پارامتر watch را شناسایی کرده‌است و دیگر از کامپایلر قدیمی tsc استفاده نمی‌کند. برای آزمایش آن، از منوی view گزینه‌ی split editor را انتخاب کنید و سپس در سمت چپ فایل test.ts و در سمت راست، فایل test.js کامپایل شده را باز کنید:


در اینجا چون پارامتر watch فعال شده‌است، هر تغییری که در فایل ts داده شود، بلافاصله کامپایل شده و در فایل js منعکس خواهد شد.


تنظیم VS Code جهت دیباگ کدهای TypeScript

در نوار ابزار کنار صفحه‌ی VS Code، بر روی دکمه‌ی دیباگ کلیک کنید:


سپس بر روی دکمه‌ی چرخ‌دنده‌ی موجود که کار انجام تنظیمات را توسط آن می‌توان ادامه داد، کلیک کنید. بلافاصله منویی ظاهر می‌شود که درخواست انتخاب محیط دیباگ را دارد:


در اینجا node.js را انتخاب کنید. با اینکار فایل جدیدی دیگری به نام launch.json به پوشه‌ی vscode. اضافه می‌شود. اگر به این فایل دقت کنید دو خاصیت name به نام‌های Launch و Attach در آن موجود هستند. این نام‌ها در یک دراپ داون، در کنار دکمه‌ی start دیباگ نیز ظاهر می‌شوند:


- در فایل launch.json، باید خاصیت "program": "${workspaceRoot}/app.js" را ویرایش کرد و app.js آن‌را به test.ts مثال جاری تغییر داد.
- سپس خاصیت "sourceMaps" آن نیز باید تغییر کرده و جهت استفاده‌ی از source mapهای تولیدی به true تنظیم شود.
- در آخر باید مسیر پوشه‌ی خروجی js را نیز تنظیم کرد: "outDir": "${workspaceRoot}/js"
همچنین باید دقت داشت چون externalConsole به false تنظیم شده‌است، خروجی این کنسول به output ویژوال استودیوکد منتقل می‌شود.

اکنون اگر بر روی دکمه‌ی سبز رنگ start کلیک کنید (دکمه‌ی F5)، امکان دیباگ سطر به سطر کد TypeScript را خواهید یافت:



فایل‌های نهایی json یاد شده‌ی در متن را از اینجا می‌توانید دریافت کنید:
 VSCodeTypeScript.zip