اشتراکها
توابع سیستمی در Sql server
اغلب برنامههای AngularJS 2.0، اطلاعات خود را از طریق پروتکل HTTP، از سرور دریافت میکنند. برنامه یک درخواست Get را صادر کرده و سپس سرور پاسخ مناسبی را ارائه میدهد.
مقدمهای بر RxJS
اگر به پیشنیازهای نصب AngularJS 2.0 در قسمت اول این سری دقت کرده باشید، یکی از موارد آن، RxJS است:
یک Observable، آرایهای است که اعضای آن به صورت غیر همزمان (asynchronously) در طول زمان دریافت میشوند. برای مثال پس از شروع یک عملیات async، ابتدا عنصر اول آرایه دریافت میشود، پس از مدتی عنصر دوم و در آخر عنصر سوم آن. به همین جهت از Observableها برای مدیریت دادههای async مانند دریافت اطلاعات از یک وب سرور، استفاده میشود.
قرار است Observableها به ES 2016 یا نگارش پس از ES 6 اضافه شوند و یکی از پیشنهادات آن هستند. اما هم اکنون AngularJS 2.0 از این امکان، توسط یک کتابخانهی ثالث، به نام reactive extensions یا Rx، استفاده میکند. از RxJS در سرویس HTTP و همچنین مدیریت سیستم رخدادهای AngularJS 2.0 استفاده میشود. Observableها امکانی را فراهم میکنند تا به ازای دریافت هر اطلاعات async از سرور، بتوان توسط رخدادهایی از وقوع آنها مطلع شد.
در نگارش قبلی AngularJS از Promises برای مدیریت اعمال غیرهمزمان استفاده میشد. Observableها تفاوتهای قابل ملاحظهای با Promises دارند:
- یک Promise تنها یک مقدار، یا خطا را بر میگرداند؛ اما یک Observable چندین مقدار را در طول یک بازهی زمانی باز میگرداند.
- برخلاف Promises، میتوان عملیات یک Observable را لغو کرد.
- Observableها از عملگرهایی مانند map، reduce، filter و غیره نیز پشتیبانی میکنند.
البته باید عنوان کرد که هنوز هم میتوان از Promises در صورت تمایل در AngularJS 2.0 نیز استفاده کرد.
تنظیمات اولیهی کار با RxJS در AngularJS 2.0
برای استفاده از RxJS در AngularJS 2.0، مراحلی مانند افزودن مدخل اسکریپت http.dev.js، ثبت پروایدر HTTP و importهای لازم، باید طی شوند که در ادامه آنها را بررسی خواهیم کرد:
الف) سرویس HTTP جزئی از angular2/core نیست. به همین جهت مدخل اسکریپت متناظر با آن، باید به صفحهی اصلی سایت اضافه شود که این مورد، در قسمت اول بررسی پیشنیازهای نصب AngularJS 2.0 صورت گرفتهاست:
این تعریف در فایل Views\Shared\_Layout.cshtml (و یا index.html) پروژهی جاری موجود است. همچنین در این صفحه، مدخل Rx.js نیز ذکر شدهاست.
ب) اکنون فایل app.component.ts را گشوده و سرویس HTTP را به آن اضافه میکنیم. با نحوهی ثبت سرویسها در قسمت قبل آشنا شدیم:
از آنجائیکه میخواهیم سرویس HTTP، در تمام کامپوننتهای برنامه در دسترس باشد، آنرا در بالاترین سطح سلسه مراتب کامپوننتهای موجود، یا همان کامپوننت ریشهی سایت، ثبت و معرفی میکنیم. بنابراین سرویس توکار HTTP یا HTTP_PROVIDERS به لیست پروایدرها، اضافه شدهاست.
ج) پس از آن نیاز است importهای متناظر نیز به ابتدای ماژول فعلی، جهت شناسایی این سرویس و همچنین امکانات rx.js اضافه شوند.
تعریف 'import 'rxjs/Rx به این شکل، به module loader اعلام میکند که این کتابخانه را بارگذاری کن، اما چیزی را import نکن. هنگامیکه این کتابخانه بارگذاری میشود، کدهای جاوا اسکریپتی آن اجرا شده و سبب میشوند که عملگرهای ویژهی Observable آن مانند map و filter نیز در دسترس برنامه قرار گیرند.
ساخت یک سرویس سمت سرور بازگشت لیست محصولات به صورت JSON
چون در ادامه میخواهیم لیست محصولات را از سرور دریافت کنیم، برنامهی ASP.NET MVC فعلی را اندکی تغییر میدهیم تا این لیست را به صورت JSON بازگشت دهد.
بنابراین ابتدا کلاس مدل محصولات را به نحو ذیل به پوشهی Models اضافه کرده:
و سپس اکشن متد Products، لیست محصولات فرضی این سرویس را بازگشت میدهد:
در اینجا از JSON.NET جهت بازگشت camel case نام خواص مورد نیاز در سمت کاربر، استفاده شدهاست.
برای مطالعهی بیشتر:
«استفاده از JSON.NET در ASP.NET MVC»
«تنظیمات و نکات کاربردی کتابخانهی JSON.NET»
به این ترتیب، آدرس http://localhost:2222/home/products، خروجی JSON سرویس لیست محصولات را در مثال جاری، ارائه میدهد.
ارسال یک درخواست HTTP به سرور توسط AngularJS 2.0
اکنون پس از تنظیمات ثبت و معرفی سرویس HTTP و همچنین برپایی یک سرویس سمت سرور ارائهی لیست محصولات، میخواهیم سرویس ProductService را که در قسمت قبل ایجاد کردیم (فایل product.service.ts)، جهت دریافت لیست محصولات از سمت سرور، تغییر دهیم:
از آنجائیکه این سرویس دارای یک وابستگی تزریق شدهاست، ذکر ()Injectable@، پیش از تعریف نام کلاس، ضروری است.
در سازندهی کلاس ProductService، کار تزریق وابستگی سرویس Http انجام شدهاست. به این ترتیب با استفاده از متغیر خصوصی http_، میتوان در کلاس جاری به امکانات این سرویس دسترسی یافت (همان «تزریق سرویسها به کامپوننتها» در قسمت قبل).
سپس متد get آن، یک درخواست HTTP از نوع GET را به آدرس مشخص شدهی در متغیر productUrl_ ارسال میکند (یا همان سرویس سمت سرور برنامه).
سرویس Http و همچنین شیء Response آن در ماژولهای Http و Response قرار دارند که در ابتدای صفحه import شدهاند.
متد http get یک Observable را بازگشت میدهد که در نهایت خروجی این متد نیز به همان <[]Observable<IProduct، تنظیم شدهاست. Observable یک شیء جنریک است و در اینجا نوع آن، آرایهای از محصولات درنظر گرفته شدهاست.
اکنون که امضای این متد تغییر یافته است (پیش از این صرفا یک آرایهی ساده از محصولات بود)، استفاده کننده (در کلاس ProductListComponent) باید به تغییرات آن از طریق متد subscribe گوش فرا دهد.
فعلا در کلاس جاری، پس از پایان کار دریافت اطلاعات از سرور، اطلاعات نهایی در متد map در دسترس قرار میگیرد (که یکی از عملگرهای RxJs است). کار متد map، اصطلاحا projection است. این متد، هر عضو دریافتی از خروجی سرور را به فرمتی جدید نگاشت میکند.
هر درخواست HTTP، در اصل یک عملیات async است. یعنی در اینجا توالی که در اختیار Observable ما قرار میگیرد، تنها یک المان دارد که همان شیء HTTP Response است.
بنابراین کار متد map فوق، تبدیل شیء خروجی از سرور، به آرایهای از محصولات است.
در اینجا یک سری کدهای مدیریت استثناءها را نیز در صورت بروز مشکلی میتوان تعریف کرد. برای مثال در اینجا متد catch، کار پردازش خطاهای رخ داده را انجام میدهد.
از متد do جهت لاگ کردن عملیات رخ داده و دادههای دریافتی در کنسول developer tools مرورگرها استفاده شدهاست.
یک نکته:
اگر خروجی JSON از سرور، برای مثال داخل خاصیتی به نام data محصور شده بود، بجای ()response.json میبایستی از response.json().data استفاده میشد.
گوش فرا دادن به Observable دریافتی از سرور
تا اینجا یک درخواست HTTP GET را به سمت سرور ارسال کردیم و خروجی آن به صورت Observable در اختیار ما است. اکنون نیاز است کدهای ProductListComponent را جهت گوش فرا دادن به این Observable تغییر دهیم. برای این منظور فایل product-list.component.ts را گشوده و تغییرات ذیل را به آن اعمال کنید:
در کلاس ProductListComponent، در متد ngOnInit که در آن کار آغاز و مقدار دهی وابستگیهای کامپوننت انجام میشود، متد ()productService.getProducts_ فراخوانی شدهاست. این متد یک Observable را بر میگرداند. بنابراین برای پردازش نتیجهی آن نیاز است متد subscribe را در ادامهی آن، زنجیر وار ذکر کرد.
اولین پارامتر متد subscribe، کار دریافت نتایج حاصل را به عهده دارد. برای مثال اگر حاصل عملیات در طی سه مرحله صورت گیرد، سه بار نتیجهی دریافتی را میتوان در اینجا پردازش کرد. البته همانطور که عنوان شد، یک عملیات غیرهمزمان HTTP، تنها در طی یک مرحله، HTTP Response را دریافت میکند؛ بنابراین، پارامتر اول متد subscribe نیز تنها یکبار اجرا میشود. در اینجا فرصت خواهیم داشت تا آرایهی دریافتی حاصل از متد map قسمت قبل را به خاصیت عمومی products کلاس جاری نسبت دهیم.
پارامتر دوم متد subscribe در صورت شکست عملیات فراخوانی میشود. در اینجا حاصل آن به خاصیت جدید errorMessage نسبت داده شدهاست.
اکنون برنامه را مجددا اجرا کنید، هنوز باید لیست محصولات، مانند قبل نمایش داده شود.
یک نکته
اگر برنامه را اجرا کردید و خروجی مشاهده نشد، به کنسول developer tools مرورگر مراجعه کنید؛ احتمالا خطای ذیل در آن درج شدهاست:
به این معنا که پروایدر HTTP یا همان HTTP_PROVIDERS، جایی معرفی نشدهاست. البته مشکلی از این لحاظ در برنامه وجود ندارد و این پروایدر در بالاترین سطح ممکن و در فایل app.component.ts ثبت شدهاست. مشکل اینجا است که مرورگر، فایل قدیمی http://localhost:2222/app/app.component.js را کش کردهاست (به همراه تمام اسکریپتهای دیگر) و این فایل قدیمی، فاقد تعریف سرویس HTTP است. بنابراین با حذف کش مرورگر و دریافت فایلهای js جدید، مشکل برطرف خواهد شد.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: MVC5Angular2.part8.zip
خلاصهی بحث
برای کار با سرور و ارسال درخواستهای HTTP، ابتدا نیاز است مدخل تعریف http.dev.js به index.html اضافه شود و سپس HTTP_PROVIDERS را در بالاترین سطح کامپوننتهای تعریف شده، ثبت و معرفی کرد. پس از آن نیاز است RxJs را نیز import کرد. در ادامه، سرویس دریافت لیست محصولات، وابستگی سرویس HTTP را توسط سازندهی خود دریافت کرده و از آن برای صدور یک فرمان HTTP GET استفاده میکند. سپس با استفاده از متد map، کار نگاشت شیء Response دریافتی، به فرمت مناسب مدنظر، صورت میگیرد.
در ادامه هر کلاسی که نیاز دارد با این کلاس سرویس دریافت اطلاعات کار کند، متد subscribe را فراخوانی کرده و نتیجهی عملیات را پردازش میکند.
مقدمهای بر RxJS
اگر به پیشنیازهای نصب AngularJS 2.0 در قسمت اول این سری دقت کرده باشید، یکی از موارد آن، RxJS است:
"dependencies": { "rxjs": "5.0.0-beta.2" },
قرار است Observableها به ES 2016 یا نگارش پس از ES 6 اضافه شوند و یکی از پیشنهادات آن هستند. اما هم اکنون AngularJS 2.0 از این امکان، توسط یک کتابخانهی ثالث، به نام reactive extensions یا Rx، استفاده میکند. از RxJS در سرویس HTTP و همچنین مدیریت سیستم رخدادهای AngularJS 2.0 استفاده میشود. Observableها امکانی را فراهم میکنند تا به ازای دریافت هر اطلاعات async از سرور، بتوان توسط رخدادهایی از وقوع آنها مطلع شد.
در نگارش قبلی AngularJS از Promises برای مدیریت اعمال غیرهمزمان استفاده میشد. Observableها تفاوتهای قابل ملاحظهای با Promises دارند:
- یک Promise تنها یک مقدار، یا خطا را بر میگرداند؛ اما یک Observable چندین مقدار را در طول یک بازهی زمانی باز میگرداند.
- برخلاف Promises، میتوان عملیات یک Observable را لغو کرد.
- Observableها از عملگرهایی مانند map، reduce، filter و غیره نیز پشتیبانی میکنند.
البته باید عنوان کرد که هنوز هم میتوان از Promises در صورت تمایل در AngularJS 2.0 نیز استفاده کرد.
تنظیمات اولیهی کار با RxJS در AngularJS 2.0
برای استفاده از RxJS در AngularJS 2.0، مراحلی مانند افزودن مدخل اسکریپت http.dev.js، ثبت پروایدر HTTP و importهای لازم، باید طی شوند که در ادامه آنها را بررسی خواهیم کرد:
الف) سرویس HTTP جزئی از angular2/core نیست. به همین جهت مدخل اسکریپت متناظر با آن، باید به صفحهی اصلی سایت اضافه شود که این مورد، در قسمت اول بررسی پیشنیازهای نصب AngularJS 2.0 صورت گرفتهاست:
<!-- Required for http --> <script src="~/node_modules/angular2/bundles/http.dev.js"></script>
ب) اکنون فایل app.component.ts را گشوده و سرویس HTTP را به آن اضافه میکنیم. با نحوهی ثبت سرویسها در قسمت قبل آشنا شدیم:
import { Component } from 'angular2/core'; import { HTTP_PROVIDERS } from 'angular2/http'; import 'rxjs/Rx'; // Load all features import { ProductListComponent } from './products/product-list.component'; import { ProductService } from './products/product.service'; @Component({ selector: 'pm-app', template:` <div><h1>{{pageTitle}}</h1> <pm-products></pm-products> </div> `, directives: [ProductListComponent], providers: [ ProductService, HTTP_PROVIDERS ] }) export class AppComponent { pageTitle: string = "DNT AngularJS 2.0 APP"; }
ج) پس از آن نیاز است importهای متناظر نیز به ابتدای ماژول فعلی، جهت شناسایی این سرویس و همچنین امکانات rx.js اضافه شوند.
تعریف 'import 'rxjs/Rx به این شکل، به module loader اعلام میکند که این کتابخانه را بارگذاری کن، اما چیزی را import نکن. هنگامیکه این کتابخانه بارگذاری میشود، کدهای جاوا اسکریپتی آن اجرا شده و سبب میشوند که عملگرهای ویژهی Observable آن مانند map و filter نیز در دسترس برنامه قرار گیرند.
ساخت یک سرویس سمت سرور بازگشت لیست محصولات به صورت JSON
چون در ادامه میخواهیم لیست محصولات را از سرور دریافت کنیم، برنامهی ASP.NET MVC فعلی را اندکی تغییر میدهیم تا این لیست را به صورت JSON بازگشت دهد.
بنابراین ابتدا کلاس مدل محصولات را به نحو ذیل به پوشهی Models اضافه کرده:
namespace MVC5Angular2.Models { public class Product { public int ProductId { set; get; } public string ProductName { set; get; } public string ProductCode { set; get; } public string ReleaseDate { set; get; } public decimal Price { set; get; } public string Description { set; get; } public double StarRating { set; get; } public string ImageUrl { set; get; } } }
using System.Collections.Generic; using System.Text; using System.Web.Mvc; using MVC5Angular2.Models; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; namespace MVC5Angular2.Controllers { public class HomeController : Controller { // GET: Home public ActionResult Index() { return View(); } public ActionResult Products() { var products = new List<Product> { new Product { ProductId= 2, ProductName= "Garden Cart", ProductCode= "GDN-0023", ReleaseDate= "March 18, 2016", Description= "15 gallon capacity rolling garden cart", Price= (decimal) 32.99, StarRating= 4.2, ImageUrl= "app/assets/images/garden_cart.png" }, new Product { ProductId= 5, ProductName= "Hammer", ProductCode= "TBX-0048", ReleaseDate= "May 21, 2016", Description= "Curved claw steel hammer", Price= (decimal) 8.9, StarRating= 4.8, ImageUrl= "app/assets/images/rejon_Hammer.png" } }; return new ContentResult { Content = JsonConvert.SerializeObject(products, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }), ContentType = "application/json", ContentEncoding = Encoding.UTF8 }; } } }
برای مطالعهی بیشتر:
«استفاده از JSON.NET در ASP.NET MVC»
«تنظیمات و نکات کاربردی کتابخانهی JSON.NET»
به این ترتیب، آدرس http://localhost:2222/home/products، خروجی JSON سرویس لیست محصولات را در مثال جاری، ارائه میدهد.
ارسال یک درخواست HTTP به سرور توسط AngularJS 2.0
اکنون پس از تنظیمات ثبت و معرفی سرویس HTTP و همچنین برپایی یک سرویس سمت سرور ارائهی لیست محصولات، میخواهیم سرویس ProductService را که در قسمت قبل ایجاد کردیم (فایل product.service.ts)، جهت دریافت لیست محصولات از سمت سرور، تغییر دهیم:
import { Injectable } from 'angular2/core'; import { IProduct } from './product'; import { Http, Response } from 'angular2/http'; import { Observable } from 'rxjs/Observable'; @Injectable() export class ProductService { private _productUrl = '/home/products'; constructor(private _http: Http) { } getProducts(): Observable<IProduct[]> { return this._http.get(this._productUrl) .map((response: Response) => <IProduct[]>response.json()) .do(data => console.log("All: " + JSON.stringify(data))) .catch(this.handleError); } private handleError(error: Response) { console.error(error); return Observable.throw(error.json().error || 'Server error'); } }
در سازندهی کلاس ProductService، کار تزریق وابستگی سرویس Http انجام شدهاست. به این ترتیب با استفاده از متغیر خصوصی http_، میتوان در کلاس جاری به امکانات این سرویس دسترسی یافت (همان «تزریق سرویسها به کامپوننتها» در قسمت قبل).
سپس متد get آن، یک درخواست HTTP از نوع GET را به آدرس مشخص شدهی در متغیر productUrl_ ارسال میکند (یا همان سرویس سمت سرور برنامه).
سرویس Http و همچنین شیء Response آن در ماژولهای Http و Response قرار دارند که در ابتدای صفحه import شدهاند.
متد http get یک Observable را بازگشت میدهد که در نهایت خروجی این متد نیز به همان <[]Observable<IProduct، تنظیم شدهاست. Observable یک شیء جنریک است و در اینجا نوع آن، آرایهای از محصولات درنظر گرفته شدهاست.
اکنون که امضای این متد تغییر یافته است (پیش از این صرفا یک آرایهی ساده از محصولات بود)، استفاده کننده (در کلاس ProductListComponent) باید به تغییرات آن از طریق متد subscribe گوش فرا دهد.
فعلا در کلاس جاری، پس از پایان کار دریافت اطلاعات از سرور، اطلاعات نهایی در متد map در دسترس قرار میگیرد (که یکی از عملگرهای RxJs است). کار متد map، اصطلاحا projection است. این متد، هر عضو دریافتی از خروجی سرور را به فرمتی جدید نگاشت میکند.
هر درخواست HTTP، در اصل یک عملیات async است. یعنی در اینجا توالی که در اختیار Observable ما قرار میگیرد، تنها یک المان دارد که همان شیء HTTP Response است.
بنابراین کار متد map فوق، تبدیل شیء خروجی از سرور، به آرایهای از محصولات است.
در اینجا یک سری کدهای مدیریت استثناءها را نیز در صورت بروز مشکلی میتوان تعریف کرد. برای مثال در اینجا متد catch، کار پردازش خطاهای رخ داده را انجام میدهد.
از متد do جهت لاگ کردن عملیات رخ داده و دادههای دریافتی در کنسول developer tools مرورگرها استفاده شدهاست.
یک نکته:
اگر خروجی JSON از سرور، برای مثال داخل خاصیتی به نام data محصور شده بود، بجای ()response.json میبایستی از response.json().data استفاده میشد.
گوش فرا دادن به Observable دریافتی از سرور
تا اینجا یک درخواست HTTP GET را به سمت سرور ارسال کردیم و خروجی آن به صورت Observable در اختیار ما است. اکنون نیاز است کدهای ProductListComponent را جهت گوش فرا دادن به این Observable تغییر دهیم. برای این منظور فایل product-list.component.ts را گشوده و تغییرات ذیل را به آن اعمال کنید:
errorMessage: string; ngOnInit(): void { //console.log('In OnInit'); this._productService.getProducts() .subscribe( products => this.products = products, error => this.errorMessage = <any>error); }
اولین پارامتر متد subscribe، کار دریافت نتایج حاصل را به عهده دارد. برای مثال اگر حاصل عملیات در طی سه مرحله صورت گیرد، سه بار نتیجهی دریافتی را میتوان در اینجا پردازش کرد. البته همانطور که عنوان شد، یک عملیات غیرهمزمان HTTP، تنها در طی یک مرحله، HTTP Response را دریافت میکند؛ بنابراین، پارامتر اول متد subscribe نیز تنها یکبار اجرا میشود. در اینجا فرصت خواهیم داشت تا آرایهی دریافتی حاصل از متد map قسمت قبل را به خاصیت عمومی products کلاس جاری نسبت دهیم.
پارامتر دوم متد subscribe در صورت شکست عملیات فراخوانی میشود. در اینجا حاصل آن به خاصیت جدید errorMessage نسبت داده شدهاست.
اکنون برنامه را مجددا اجرا کنید، هنوز باید لیست محصولات، مانند قبل نمایش داده شود.
یک نکته
اگر برنامه را اجرا کردید و خروجی مشاهده نشد، به کنسول developer tools مرورگر مراجعه کنید؛ احتمالا خطای ذیل در آن درج شدهاست:
EXCEPTION: No provider for Http!
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: MVC5Angular2.part8.zip
خلاصهی بحث
برای کار با سرور و ارسال درخواستهای HTTP، ابتدا نیاز است مدخل تعریف http.dev.js به index.html اضافه شود و سپس HTTP_PROVIDERS را در بالاترین سطح کامپوننتهای تعریف شده، ثبت و معرفی کرد. پس از آن نیاز است RxJs را نیز import کرد. در ادامه، سرویس دریافت لیست محصولات، وابستگی سرویس HTTP را توسط سازندهی خود دریافت کرده و از آن برای صدور یک فرمان HTTP GET استفاده میکند. سپس با استفاده از متد map، کار نگاشت شیء Response دریافتی، به فرمت مناسب مدنظر، صورت میگیرد.
در ادامه هر کلاسی که نیاز دارد با این کلاس سرویس دریافت اطلاعات کار کند، متد subscribe را فراخوانی کرده و نتیجهی عملیات را پردازش میکند.
مباحث جداول بهینه سازی شده برای حافظه، روی این سیستم تهیه شدند:
با این خروجی (که مشخصات instance جاری را بر میگرداند؛ در مثال شما 'instance ' TFS-SERVER باید بررسی شود که چه نگارشی دارد)
select @@VERSION
Microsoft SQL Server 2014 - 12.0.2254.0 (X64) Jul 25 2014 18:52:51 Copyright (c) Microsoft Corporation Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: )
ذخیره سازی فایلهای باینری در بانک اطلاعاتی هیچگاه ایدهی خوبی نبوده. این وضعیت با ارائهی SqlFileStream به همراه SQL Server 2008 بهبود یافت و به این صورت تنها یک اشارهگر به فایل در بانک اطلاعاتی ذخیره میشود و نه اصل فایل. پس از آن FileTable به همراه SQL Server 2012 ارائه شد که نسخهی بهبود یافتهی FileStream به شمار میرود و توسط آن امکان دسترسی به متادیتای فایل، درون SQL Server و همچنین امکان کار با فایلها در خارج از SQL Server هم پشتیبانی میشوند. بنابراین اگر از SQL Server 2012 به بعد استفاده میکنید، روش ترجیح داده شده، کار با FileTable است: یک مثال کامل از نحوهی کار با FileTable در NET Core.
+ پشتیبانی کامل از FileStream جزئی از NET Core 3x. خواهد بود.
گاهی اوقات بدلیل تغییرات در جداول و غیرو...، ممکن است لازم شود، از استفاده قرار گرفتن فیلدهای جداول درون Function ها،Stored Procedureها و یا Viewها ، مطلع شوید. در این زمان شما میتوانید از روش زیر استفاده نماید.
قبل از هر چیز در ابتدا Script زیر را اجرا نمایید.که شامل یک جدول به نام FindField ، یک Stored Procedure به نام PROCEDURE_FindField و یک Function به نام FUNCTION_FindField میباشد.
در ادامه Script زیر را اجرا نمایید:
خروجی بصورت زیر خواهد بود:
قبل از هر چیز در ابتدا Script زیر را اجرا نمایید.که شامل یک جدول به نام FindField ، یک Stored Procedure به نام PROCEDURE_FindField و یک Function به نام FUNCTION_FindField میباشد.
Create Table FindField (ID int, Firstname varchar(255), Lastname varchar(255)) Go CREATE PROCEDURE PROCEDURE_FindField AS SELECT Firstname FROM FindField; GO CREATE FUNCTION FUNCTION_FindField (@id int) RETURNS int WITH EXECUTE AS CALLER AS begin declare @id1 int; set @id1= (Select Max(Firstname) from dbo.FindField) ; RETURN (@id1); END;
SELECT OBJECT_NAME(object_id) as 'Procedure/Function/View Name', definition FROM sys.sql_modules WHERE definition LIKE '%' + 'Firstname' + '%'
همانطور که در شکل مشاهده مینمایید، فیلد Firstnameدر Function و Stored Procedure مورد استفاده واقع شده است.
جهت کسب اطلاعات بیشتر به آدرس زیر مراجعه نمایید:
Curry and Partial methods
Curry – در ریاضیات و علوم کامپیوتر، currying روشی است برای ترجمه تابعی که آرگومانهای متعددی میگیرد و به صورت ارزیابی دنبالهایاست از توابع که هر کدام یک آرگومان دارند.
برای پیاده سازی آن در #C، از extension methods استفاده میکنیم.
public static class CurryMethodExtensions { public static Func< A, Func< B, Func< C, R > > > Curry< A, B, C, R >( this Func< A, B, C, R > f ) { return a => b => c => f( a, b, c ); } }
Func< int, int, int, int > addNumbers = ( x, y, z ) => x + y + z; var f1 = addNumbers.Curry(); Func< int, Func< int, int > > f2 = f1( 3 ); Func< int, int > f3 = f2( 4 ); Console.WriteLine( f3( 5 ) );
نحوه اجرای دستورات بالا را در تصویر زیر میتوانید مشاهده کنید:
Partial – در علوم کامپیوتر، قسمتی از یک برنامه (یا قسمتی از یک تابع برنامه) است که اشاره به روند تثبیت تعدادی از آرگومانها به یک تابع و تولید تعداد آرگومانهای کمتر تابع دیگری را میگویند.
public static class CurryMethodExtensions { public static Func< C, R > Partial< A, B, C, R >( this Func< A, B, C, R > f, A a, B b ) { return c => f( a, b, c ); } }
Func< int, int, int, int > sumNumbers = ( x, y, z ) => x + y + z; Func< int, int > f4 = sumNumbers.Partial( 3, 4 ); Console.WriteLine( f4( 5 ) );
بعد از فراخوانی متد Curry میتوان از کلمه کلیدی var در دستورات بعدی بجای تعریف نوع متغیرها استفاده کرد.
نحوه اجرای دستورات بالا را در تصویر زیر میتوانید مشاهده کنید:
WeakReference
یک ارجاع ضعیف به GC اجازه میدهد که یک شیء را جمع آوری کند، در عین حالی که برنامه امکان دسترسی به آن را خواهد داشت. در صورتیکه نیاز به شیءای داشته باشید، میتوانید یک ارجاع قوی را از آن داشته باشید و از جمع آوری آن توسط GC جلوگیری کنید.
var obj = new WeakReferenceTest { FirstName = "Vahid" }; var w = new WeakReference(obj); obj = null; GC.Collect(); var weakReferenceTest = w.Target as WeakReferenceTest; if ( weakReferenceTest != null ) Console.WriteLine( weakReferenceTest.FirstName );
Lazy<T>
برای ایجاد یک شیء بزرگ، پردازش زیاد منابع و یا اجرای یک وظیفه (task) با پردازش زیاد منابع، به خصوص در زمانیکه ایجاد و یا اجرای این فرآیند در طول عمر یک برنامه، ممکن است هرگز رخ ندهد، از Lazy استفاده میشود.
public abstract class ThreadSafeLazyBaseSingleton< T > where T : new() { static readonly Lazy< T > lazy = new Lazy< T >( () => new T() ); public static T Instance => lazy.Value; }
BigInteger
نوع داده BigInteger یک نوع تغییر ناپذیر (immutable type) و نمایانگر یک عدد صحیح بزرگ دلخواه است که مقدار آن در تئوری در هیچ حد و مرز حداقل و حداکثری نیست. این نوع، از دیگر انواع جدایی ناپذیر (integral types) در NET.، که دارای خصوصیت MinValue و MaxValue هستند، متفاوت است.
var positiveString = "91389681247993671255433422114345532000000"; var negativeString = "-9031583741089631207100208803453423537140000"; var posBigInt = BigInteger.Parse( positiveString ); Console.WriteLine( posBigInt ); var negBigInt = BigInteger.Parse( negativeString ); Console.WriteLine( negBigInt );
در ردهی بانکهای اطلاعاتی سبک و رایگان، SQL Server CE و همچنین SQLite به صورت توکار (بدون نیاز به کدنویسی خاصی) از رمزنگاری کل بانک اطلاعاتی پشتیبانی میکنند.
برای گرفتن خروجی مناسب از FTS نیاز هست یک سری نکات ویژه را رعایت کرد؛ اطلاعات بیشتر در دورهی پشتیبانی از Full Text Search در SQL Server مطرح شدهاند.