PHP سریعتر از ASP.NET! افسانه یا واقعیت؟
چندین علت داره:
- پروسه کامپایل کدهای دات نت یک مرحلهای نیست. کلا در دات نت کدها به یک زبان میانی به نام IL ترجمه میشن. بعد این IL توسط JIT compiler تبدیل به کدهای ماشین میشه. در ASP.NET این مساله هم برای کدهای پشت صحنه برنامه و هم برای خود صفحات رخ میده. بنابراین برای بار اول مشاهده، روند این پروسه الزامی هست. ولی برای دفعات بعدی مشاهده خیر. البته روش برای پیش کامپایل کردن کامل صفحات هم وجود داره و یا در IISهای جدید یک سری مبحث warmup توکار پیش بینی شده.
- همچنین IIS برای مدیریت منابع سرور، یک سایت رو مدام در حافظه نگه نمیداره. فقط زمانیکه اولین درخواست به سرور میرسه سایت رو بارگذاری میکنه و application pool اون رو استارت. این هم یک زمان اولیه اندکی رو ممکنه به خودش اختصاص بده. بعلاوه پس از مدتی، یک سایت بیکار رو از حافظه خارج میکنه. بهش میگن ریسایکل کردن. در ASP.NET 4.0 به بعد امکان تنظیم auto-start برای سایتها هست.
خلاصهای کوتاه در مورد WinRT
ضمنا این محدودیتهای امنیتی ذکر شده برای آن قطعا برای خیلی از برنامه نویسها خوشایند نخواهد بود. برای دسترسی بیشتر، مجبور خواهند شد به سیستمهای دسکتاپ سابق رجوع کنند.
- free - List of freely available programming books - Stack Overflow | stackoverflow.com
- افزونه گوگل پلاس کروم | chrome.google.com
- آمار سورس فورج در مورد تعداد کاربران از سیستم عاملهای مختلف | sourceforge.net
- انتشار SQL Server 2012 RC | blogs.technet.com
- بدنبال دلیل برای ادامه کار با NHibernate | www.linkedin.com
- دسکتاپ ویندوز 7 خود را بهتر مدیریت کنید | www.hanselman.com
- ساخت یک RSS Reader با دات نت میکرو فریم ورک | channel9.msdn.com
- فسلفهی وجودی IL چیست؟ چرا کدهای دات نت از همان ابتدا مستقیما به زبان ماشین ترجمه نمیشوند؟ | blogs.msdn.com
- کدهای CSS را در ویژوال استودیو سریعتر تایپ کنید | madskristensen.net
تنظیمات برنامه BloggerToChm را به دات نت 4 تغییر دادم و بدون مشکل کامپایل شد. اما حین اجرا بلافاصله با خطای زیر برنامه اجرا نمیشد:
Mixed mode assembly is built against version 'v2.0.50727' of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information.
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0"/>
</startup>
</configuration>
- Velocity CTP3 ارائه شد.
پروژه سورس بازی است که از بسیاری از ماژولهای جدید دات نت فریم ورک استفاده میکند و نکتهی جالب نگارش جدید آن مهاجرت از MS Ajax به jQuery Ajax است (قسمت اجکس آن کلا از صفر بر اساس jQuery بازنویسی شده است).
- چک لیستی که پیش از برپایی یک وب سایت باید بررسی شود.
- نگارش بتا Ext Core 3.0 ارائه شد.
- یک سری برگههای مرجع لینوکسی!
- دمویی در مورد ویندوز Azure و سرویسهای مبتنی بر آن
یکی کردن اسمبلیهای یک پروژهی WPF
- یک try/catch در قسمت بارگذاری اسمبلی قرار دهید تا بهتر منبع مشکل را شناسایی کنید. یک مثال
- شخص دیگری در اینجا گزارش داده اگر Generate serialization assembly در قسمت تنظیمات پروژه، ذیل Build > Output فعال است، باید خاموش شود تا پروژه کرش نکند.
- اگر نوع اسمبلی، PCL است (Portable Class Library)، باز هم روش Assembly.Load به نحوی که در مطلب ذکر شده کار نمیکند و باید به صورت ذیل اصلاح شود:
private static Assembly loadEmbeddedAssembly(string name) { if (name.EndsWith("Retargetable=Yes")) { return Assembly.Load(new AssemblyName(name)); } // Rest of your code //... }
[MethodImpl(MethodImplOptions.NoOptimization)]
الف) از نیوگت استفاده کردهاید
در این حالت فقط کافی است کنسول پاورشل نیوگت را در VS.NET گشوده و دستور update-package را صادر کنید. (1) به صورت خودکار آخرین نگارش EF دریافت شده و (2) همچنین فایل کانفیگ برنامه برای افزودن و به روز رسانی تعاریف مرتبط با نگارش 6 به روز گردیده و (3) همچنین اسمبلی اضافی و قدیمی System.Data.Entity.dll نیز حذف خواهد شد.
ب) اگر از نیوگت استفاده نکردهاید
ابتدا یک فایل متنی ساده را به نام packages.config با محتوای ذیل به پروژه خود اضافه کنید.
<?xml version="1.0" encoding="utf-8"?> <packages> <package id="EntityFramework" version="5.0.0" targetFramework="net40" /> </packages>
لازم به ذکر است، اگر پروژه شما از چندین زیر پروژه تشکیل شده است که هر کدام نیز ارجاعی را به اسمبلی EF دارند، باید فایل packages.config فوق را به این زیر پروژهها نیز اضافه کنید. دستور update-package، زیر پروژهها را نیز اسکن کرده و تمام ارجاعات لازم را به صورت خودکار به روز میکند. همچنین اسمبلیهای قدیمی اضافی را نیز حذف خواهد کرد. به این ترتیب با تداخل نگارشهای قدیمی و جدید EF مواجه نخواهید شد.
مشکلاتی که ممکن است با آنها مواجه شوید:
الف) برنامه کامپایل نمیشود
تنها تغییری که جهت کامپایل برنامه باید انجام دهید، استفاده از فضاهای نام جدید بجای فضاهای قدیمی موجود در اسمبلی منسوخ و حذف شده System.Data.Entity.dll است. خود VS.NET قابلیت یافتن فضاهای نام مرتبط را دارد و یا اگر از Resharper نیز استفاده میکنید، این قابلیت بهبود یافته است. در کل مثلا System.Data.EntityState شده است System.Data.Entity.EntityState و امثال آن که به روز رسانی آنها نکته خاصی ندارد .
ب) پروایدر بانک اطلاعاتی مورد استفاده یافت نمیشود
به صورت پیش فرض فقط پروایدر SQL Server به همراه بسته EF 6 است. حتی پروایدر SQL Server CE نیز با آن ارائه نمیشود. اگر از SQL Server CE استفاده کردهاید، باید دستور ذیل را نیز پس از نصب EF 6 صادر کنید:
PM> Install-Package EntityFramework.SqlServerCompact
No Entity Framework provider found for the ADO.NET provider with invariant name 'System.Data.SqlServerCe.4.0'. Make sure the provider is registered in the 'entityFramework' section of the application config file. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information.
ج) خطای عدم وجود کلید خارجی جدول Migration را دریافت میکنید
The foreign key constraint does not exist. [ PK_dbo.__MigrationHistory ]
ALTER TABLE [__MigrationHistory] ADD CONSTRAINT [PK___MigrationHistory] PRIMARY KEY ([MigrationId]);
برای حل این مشکل تنها کافی است دستورات ذیل را یکبار بر روی بانک اطلاعاتی خود صادر کنید تا نام مورد نظر به عنوان کلید اصلی جدول migration اضافه شود؛ در غیراینصورت اصلا برنامه اجرا نخواهد شد:
ALTER TABLE [__MigrationHistory] drop CONSTRAINT [PK___MigrationHistory]; ALTER TABLE [__MigrationHistory] ADD CONSTRAINT [PK_dbo.__MigrationHistory] PRIMARY KEY (MigrationId);
مهمترین عیب این روش این است که در این حالت تمام متدهای این سرویس رو هم به صورت Sync و هم به صورت Async تولید میکنه در حالی که ما فقط نیاز به یک متد Async داریم.
در این پست قصد دارم پیاده سازی این متد رو بدون استفاده از Async&Await و Code Generation توکار دات نت شرح بدم که با دات نت 3.5 هم سازگار است.
ابتدا یک پروژه از نوع WCF Service Application ایجاد کنید.
یک ClassLibrary جدید به نام Model بسازید و کلاس زیر را به عنوان مدل در آن قرار دهید.(این اسمبلی باید هم به پروژههای کلاینت و هم به پروژههای سرور رفرنس داده شود)
[DataContract] public class Book { [DataMember] public int Code { get; set; } [DataMember] public string Title { get; set; } [DataMember] public string Author { get; set; } }
#Class Library به نام Contract بسازید. قصد داریم از این لایه به عنوان قراردادهای سمت کلاینت و سرور استفاده کنیم. اینترفیس زیر را به عنوان BookContract در آن بسازید.
[ServiceContract] public interface IBookService { [OperationContract( AsyncPattern = true )] IAsyncResult BeginGetAllBook( AsyncCallback callback, object state ); IEnumerable<Book> EndGetAllBook( IAsyncResult asyncResult ); }
[OperationContract] IEnumerable<Book> GetAllBook(int code , AsyncCallback callback, object state );
public class CompletedAsyncResult<TEntity> : IAsyncResult where TEntity : class , new() { public IList<TEntity> Result { get { return _result; } set { _result = value; } } private IList<TEntity> _result; public CompletedAsyncResult( IList<TEntity> data ) { this.Result = data; } public object AsyncState { get { return ( IList<TEntity> )Result; } } public WaitHandle AsyncWaitHandle { get { throw new NotImplementedException(); } } public bool CompletedSynchronously { get { return true; } } public bool IsCompleted { get { return true; } } }
public class BookService : IBookService { public BookService() { ListOfBook = new List<Book>(); } public List<Book> ListOfBook { get; private set; } private List<Book> CreateListOfBook() { Parallel.For( 0, 10000, ( int counter ) => { ListOfBook.Add( new Book() { Code = counter, Title = String.Format( "Book {0}", counter ), Author = "Masoud Pakdel" } ); } ); return ListOfBook; } public IAsyncResult BeginGetAllBook( AsyncCallback callback, object state ) { var result = CreateListOfBook(); return new CompletedAsyncResult<Book>( result ); } public IEnumerable<Book> EndGetAllBook( IAsyncResult asyncResult ) { return ( ( CompletedAsyncResult<Book> )asyncResult ).Result; } }
#کدهای سمت کلاینت:
اکثر برنامه نویسان با استفاده از روش AddServiceReference یک سرویس کلاینت در اختیار خواهند داشت که با وهله سازی از این کلاس یک ChannelFactory ایجاد میشود. در این پست به جای استفاده از Code Generation توکار دات نت برای ساخت ChannelFactory از روش دیگری استفاده خواهیم کرد. به عنوان برنامه نویس باید بدانیم که در پشت پرده عملیات ساخت ChannelFactory چگونه است.
بعد از اضافه شدن سرویس سمت کلاینت کدهای زیر برای سرویس Book به صورت زیر تولید میشود.
[System.Diagnostics.DebuggerStepThroughAttribute()] [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] public partial class BookServiceClient : System.ServiceModel.ClientBase<UI.BookService.IBookService>, UI.BookService.IBookService { public BookServiceClient() { } public BookServiceClient(string endpointConfigurationName) : base(endpointConfigurationName) { } public BookServiceClient(string endpointConfigurationName, string remoteAddress) : base(endpointConfigurationName, remoteAddress) { } public BookServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : base(endpointConfigurationName, remoteAddress) { } public BookServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : base(binding, remoteAddress) { } public UI.BookService.Book[] BeginGetAllBook() { return base.Channel.BeginGetAllBook(); } }
System.ServiceModel.ClientBase<UI.BookService.IBookService>
یک پروژه ConsoleApplication سمت کلاینت ایجاد کنید. برای فراخوانی متدهای سرویس سمت سرور باید ابتدا تنظیمات EndPoint رو به درستی انجام دهید. سپس با استفاده از EndPoint به راحتی میتوانیم Channel مربوطه را بسازیم.
کلاسی به نام ServiceMapper ایجاد میکنیم که وظیفه آن ساخت ChannelFactory به ازای درخواستها است.
public class ServiceMapper<TChannel> { public static TChannel CreateChannel() { TChannel proxy; var endPointAddress = new EndpointAddress( "http://localhost:7000/" + typeof( TChannel ).Name.Remove( 0, 1 ) + ".svc" ); var httpBinding = new BasicHttpBinding(); ChannelFactory<TChannel> factory = new ChannelFactory<TChannel>( httpBinding, endPointAddress ); proxy = factory.CreateChannel(); return proxy; } }
"http://localhost:7000/" + "BookService.svc"
بعد از اعمال تغییرات زیر در فایل Program پروژه Console و اجرای آن، خروجی به صورت زیر میباشد.
var channel = ServiceMapper<Contract.IBookService>.CreateChannel(); channel.BeginGetAllBook( new AsyncCallback( ( asyncResult ) => { channel.EndGetAllBook( asyncResult ).ToList().ForEach( _record => { Console.WriteLine( _record.Title ); } ); } ) , null ); Console.WriteLine( "Loading..." ); Console.ReadLine();
خروجی :
نکته: برای اینکه مطمئن شوید که سرویس مورد نظر در آدرس "http"//localhost:7000/" هاست شده است(یعنی همان آدرسی که در EndPointAddress از آن استفاه کردیم) کافیست از پنجره Project Properties برای پروژه سرویس وارد برگه Web شده و از بخش Servers گزینه Use Visual Studio Development Server و Specific Port 7000 رو انتخاب کنید.
پارامترها در ES 6
Destructuring Arrays
بدون استفاده از Destructuring assignment برای دسترسی به اعضای یک آرایه و انتساب آنها به متغیرهای مختلف، روش متداول زیر مرسوم است:
var first = someArray[0]; var second = someArray[1]; var third = someArray[2];
var [first, second, third] = someArray;
یک مثال:
let [one, two, three] = ['globin', 'ghoul', 'ghost', 'white walker']; console.log(`one is ${one}, two is ${two}, three is ${three}`) // => one is globin, two is ghoul, three is ghost
همچنین در این مثال اگر علاقمند بودیم صرفا به اعضای اول و چهارم این آرایه دسترسی پیدا کنیم، میتوان نوشت:
let [firstMonster, , , fourthMonster] = ['globin', 'ghoul', 'ghost', 'white walker']; console.log(`the first monster is ${firstMonster}, the fourth is ${fourthMonster}`) // => one is globin, two is ghoul, three is ghost
امکان دسترسی به اعضای تو در تو نیز با Destructuring assignment پیش بینی شدهاست:
let nested = [1, [2, 3], 4]; let [a, [b], d] = nested; console.log(a); // 1 console.log(b); // 2 console.log(d); // 4
میتوان از Destructuring assignment جهت جابجایی مقادیر متغیرها بدون انتساب به یک متغیر موقتی نیز استفاده کرد:
let point = [1, 2]; let [xVal, yVal] = point; [xVal, yVal] = [yVal, xVal]; console.log(xVal); // 2 console.log(yVal); // 1
Destructuring Objects
امکانات Destructuring assignment، به کار با آرایهها محدود نمیشود و از آن میتوان برای کار با اشیاء نیز استفاده کرد. فرض کنید شیء pouch به صورت زیر تعریف شدهاست:
let pouch = {coins: 10};
let coins = pouch.coins;
let {coins} = pouch;
let pouch = {coins: 10}; let {coins: newVar1 } = pouch; console.log(newVar1); //10
در اینجا نیز امکان کار با اشیای تو در تو، پیش بینی شدهاست:
let point = { x: 1, y: 2, z: { one: 3, two: 4 } }; let { x: a, y: b, z: { one: c, two: d } } = point; console.log(a); // 1 console.log(b); // 2 console.log(c); // 3 console.log(d); // 4
در انتساب فوق، خاصیت x شیء point به متغیر جدید a، خاصیت y شیء point به متغیر جدید b و خاصیت one شیء منتسب به خاصیت z، به متغیر c و خاصیت two شیء منتسب به خاصیت z، به متغیر d انتساب یافتهاند.
ترکیب Destructuring Objects و Destructuring Arrays
در مثال زیر، نمونهای ترکیبی از Destructuring اشیاء و آرایهها را با هم مشاهده میکنید:
let mixed = { one: 1, two: 2, values: [3, 4, 5] }; let { one: a, two: b, values: [c, , e] } = mixed; console.log(a); // 1 console.log(b); // 2 console.log(c); // 3 console.log(e); // 5
Destructuring Function Arguments
از Destructuring در حین تعریف پارامترهای متدها نیز میتوان استفاده کرد.
function removeBreakpoint({ url, line, column }) { // ... }
و یا برای مثال در زبان #C امکان تعریف named arguments (آرگومانهای نامدار) و همچنین تعریف مقادیر پیش فرضی برای آنها وجود دارد. در اینجا نیز میتوان با استفاده از Destructuring به تعریفی مشابه آن برای ارائهی آرگومانهایی با مقادیر پیش فرض رسید:
function random ({ min=1, max=300 }) { return Math.floor(Math.random() * (max - min)) + min } console.log(random({})) // <- 174 console.log(random({max: 24})) // <- 18
و یا اینبار jQuery Ajax را میتوان با پارامترهای پیش فرض آن به صورت ذیل خلاصه نویسی کرد:
jQuery.ajax = function (url, { async = true, beforeSend = noop, cache = true, complete = noop, crossDomain = false, global = true, // ... more config }) { // ... do stuff };
function returnMultipleValues() { return [1, 2]; } var [foo, bar] = returnMultipleValues();
شبیه به همین مورد در حین کار با اشیاء نیز میسر است:
function returnMultipleValues() { return { foo: 1, bar: 2 }; } var { foo, bar } = returnMultipleValues();
تعریف مقادیر پیش فرض در حین Destructuring
در انتساب ذیل، چون شیء سمت راست، دارای خاصیت foo نیست، مقدار این پارامتر جدید undefined خواهد بود. برای رفع این مشکل میتوان به آن مقدار پیش فرضی را نیز نسبت داد:
var {foo=3} = { bar: 2 } console.log(foo) // <- 3
اگر مقدار پیش فرض، ذکر شود و خاصیت متناظر با آن دارای مقدار باشد، از همان مقدار اصلی ذکر شده استفاده میشود:
var {foo=3} = { foo: 2 } console.log(foo) // <- 2
var {foo=3} = { foo: undefined } console.log(foo) // <- 3
var [b=10] = [undefined] console.log(b) // <- 10 var [c=10] = [] console.log(c) // <- 10
ES6 — default + rest + spread
علاوه بر destructuring، سه قابلیت و بهبود دیگر نیز در زمینهی کار با متغیرها و پارامترها به ES 6 اضافه شدهاند:
1) امکان تعریف مقادیر پیش فرض پارامترها
function inc(number, increment) { increment = increment || 1; return number + increment; } console.log(inc(2, 2)); // 4 console.log(inc(2)); // 3
function inc(number, increment = 1) { return number + increment; } console.log(inc(2, 2)); // 4 console.log(inc(2)); // 3
function sum(a, b = 2, c) { return a + b + c; } console.log(sum(1, 5, 10)); // 16 -> b === 5 console.log(sum(1, undefined, 10)); // 13 -> b as default
function getDefaultIncrement() { return 1; } function inc(number, increment = getDefaultIncrement()) { return number + increment; } console.log(inc(2, 2)); // 4 console.log(inc(2)); // 3
2) Spread
متد جمع زیر را درنظر بگیرید:
function sum(a, b, c) { return a + b + c; }
var args = [1, 2, 3]; console.log(sum(…args)); // 6
var args = [1, 2]; console.log(sum(…args, 3)); // 6
مثالهایی از ساده سازی اعمال متداول در ES 5 (جاوا اسکریپت فعلی) با کمک ES 6:
الف) ترکیب spread و Destructuring
a = list[0], rest = list.slice(1)
[a, ...rest] = list
ب) ساده سازی کار با concat
بجای
[1, 2].concat(more)
[1, 2, ...more]
ج) افزودن یک رنج به یک آرایه
بجای
list.push.apply(list, [3, 4])
list.push(...[3, 4])
3) Rest
جاوا اسکریپت دارای شیءایی است به نام arguments که توسط آن میتوان به لیست پارامترهای یک متد دسترسی یافت. برای نمونه مثال ذیل را درنظر بگیرید:
function sum() { var numbers = Array.prototype.slice.call(arguments), result = 0; numbers.forEach(function (number) { result += number; }); return result; }
console.log(sum(1)); // 1 console.log(sum(1, 2, 3, 4, 5)); // 15
function sum(…numbers) { var result = 0; numbers.forEach(function (number) { result += number; }); return result; } console.log(sum(1)); // 1 console.log(sum(1, 2, 3, 4, 5)); // 15
در اینجا باید دقت داشت که پس از ذکر rest، دیگر نمیتوان پارامتری را تعریف کرد:
function sum(…numbers, last) { // causes a syntax error