‫‫C#‎ برای توسعه برنامه‌های dynamic

به غیر از ما، خیلی‌های دیگر هم به فکر توسعه برنامه‌های dynamic با C#‎ و ‎.Net هستند. به عنوان نمونه به تلاش مایکروسافت در نسخه‌های ۳ و بعد از ۳ دات‌نت دقت کنید (LINQ و بقیه) یا به کتاب‌هایی مثل Pro Dynamic .NET 4.0 Applications: Data-Driven Programming for the .NET Framework نگاهی بیندازید.

آیا واقعاً این احتمال وجود ندارد که ما در حال استفاده از یک زبان و محیط اشتباه برای رسید به مقصودمان هستیم؟ زبان‌هایی مثل سی‌شارپ و جاوا استاتیک هستند، در حالی که ما هر روز در حال ساخت برنامه‌های dynamic مثل فرم‌ساز، گزارش‌ساز و… هستیم. من خودم به شخصه هیچ وقت به طور جدی به جز زبان‌های خانواده سی و پاسکال از هیچ زبان دیگری استفاده نکرده‌ام. ولی با این حال کم کم دارم به درست بودن استفاده از سی‌شارپ برای تولید نرم‌افزارهای dynamic شک می‌کنم. کم کم زمان آن رسیده که نگاهی به زبان‌های دینامیک مثل Ruby بیندازیم.

‫معرفی کتاب Pro C# 2008 and the .NET 3.5 Platform

خواندن این کتاب را مدت‌ها پیش شروع کرده بودم اما تا حالا فرصتی نشده بود که نظرم را راجع به آن بگویم. این کتاب حجیم ۱۴۰۰ صفحه‌ای همه چیز را راجع به C# 2008 به آدم یاد می‌دهد و می‌تواند به عنوان یک مرجع دائمی مورد استفاده قرار گیرد. مطالب این کتاب آنقدر جامع و کامل هستند که حتی در فصول مقدماتی و ساده آن هم می‌تواند چیزی را برای یادگیری پیدا کرد. این کتاب شامل ۳۳ فصل و ۲ ضمیمه می‌باشد.

فصل اول و دوم مقدماتی راجع به دات‌نت و C#‎ می‌گویند که دانستن آنها مفید خواهد بود. خصوصاً فصل اول که ابزار پراستفاده ildasm.exe را معرفی می‌کند.

فصل ۳ و ۴ ساختارهای اصلی C#‎ را توضیح می‌دهد که فکر می‌کنم هر کسی که کمی C#‎ بلد باشد اینها را هم بلد باشد.

فصل ۵ و ۶ راجع به ساختار شی گرا در زبان C#‎ می‌باشد. خواندن این فصل خصوصاً فصل ۶ به کسانی که می‌خواهند C#‎ را به خوبی بفهمند توصیه می‌گردد.

فصل ۷ راجع به Exception Hadling است. خیلی برنامه‌ها بدون یک Exception Handling خوب هم کار می‌کنند. اما یک Exception Handling خوب تاثیر زیادی در کیفیت برنامه دارد و باعث می‌شود خطایابی و نگهداری آن خیلی راحت‌تر باشد.

فصل ۸ راجع به چرخه زندگی Objectها در C#‎ است. دانستن مطالب این فصل برای مواقعی که بعضی چیزها را در C#‎ نمی‌فهمید خیلی مفید است. مع الوصف بنده به شخصه دانستن این اطلاعات را ضروری می‌دانم.

فصل ۹ و ۱۰ راجع به Interfaceها و Collectionها و Generic می‌باشد. ناگفته پیداست که دانستن این‌ها هم برای یک برنامه‌نویس حرفه‌ای خصوصاً آنها که به طراحی هم علاقه دارند خیلی لازم است.

فصول ۱۱ الی ۱۳ راجع به امکاناتی از C#‎ صحبت می‌کند که هم جز مباحث پیشرفته و به در بخور آن محسوب می‌شوند و هم مقدمه‌ای بر LINQ هستند. یعنی استفاده موثر از LINQ بدون آنها امکان پذیر نیست. برخی مطالب این سه فصل عبارتند از Delegate، Event، Lambda، Indexer، Automatic Properties و Extension Methodها.

فصل ۱۴ اختصاص دارد به مقدمه‌ای از LINQ. اگر این مقدار از LINQ کارتان را راه نینداخت که قریب به یقین همین طور است باید از منابع دیگری برای یادگیری تکمیلی LINQ استفاده کنید. بنده خودم به شخصه از کتاب LINQ in Action استفاده کردم.

فصول ۱۵ الی ۱۹ کلاً راجع به اسمبلی‌ها یا همان dllها و مباحث مرتبط با آنهاست. راجع به ساختار داخلی آنها، کار با آنها از طریق Reflection، مسائل مرتبط با AppDomainها، برنامه‌های چند ریسمانی (Multi Thread) و CIL و Dynamic Assemblies. به نظر شخصی من مطالب این چند فصل آنقدر خاص هستند که ممکن است خیلی‌ها هیچ وقت به آن نیاز پیدا نکنند. توصیه می‌کنم بعد از آن که فهمیدید هر کدام از این فصول راجع به چه موضوعی صحبت می‌کنند آنها را رها کرده و هر وقت که واقعاً به آنها نیاز داشتید به سراغشان بروید. بنده به شخصه فقط مبحث Reflection را مطالعه کردم و فکر هم می‌کنم حالا حالاها به غیر از مبحث چند ریسمانی به بقیه مطالب آن بی‌نیاز باشم.

فصول ۲۰ الی ۲۶ راجع به Class Library دات‌نت می‌باشند. بیشتر افراد با بعضی مطالب این فصول از قبل آشنا هستند و خیلی‌ها هم ممکن است هیچ نیاز پیدا نکنند و یا نخواهند که از بعضی از آنها استفاده کنند. مطالب این فصول به نظر من باید به صورت Reference مطالعه شوند. یعنی تا زمانی که واقعاً به آنها نیاز نشده نباید سراغشان رفت. مطالب این فصول عبارتند از IO، Object Serialization، ADO.NET، LINQ API، WCF و WF.

فصول ۲۷ الی ۳۳ کمی از خود C#‎ فاصله گرفته و به برنامه‌نویسی UI در دات‌نت می‌پردازند. این فصول مطالبی را راجع به Windows Forms، WPF و ASP.NET بیان می‌کنند. به نظر شخصی من جای این طور مطالب در یک کتاب تخصصی C#‎ نیست. یعنی اگر کسی بخواهد ASP.NET یاد بگیرد بهتر است به یک کتاب اختصاصی راجع به ASP.NET مراجعه کند نه یک کتاب C#‎. با توجه به این موضوع و با توجه به این که مطالب مطرح شده در این فصول خصوصاً در مورد ASP.NET کمی مقدماتی هستند، بنده هیچ کدام آنها را نخوانده و به کسی هم توصیه نمی‌کنم. خصوصاً این که خود من به دنبال درک بهتر C#‎ به سراغ این کتاب آمدم نه به دنبال یادگیری مقدماتی ASP.NET.

ضمیمه اول ممکن است به درد کسانی که مجبورند در دات‌نت از اشیای قدیمی COM استفاده کنند بخورد. ضمیمه دوم هم راجع به مونو است که فکر می‌کنم حالا دیگر حسابی out of date شده باشد.

پ. ن.: 
۱- ظاهراً این کتاب به فارسی هم ترجمه شده. نگاهی به اینجا بیندازید.

۲- بلد بودن بعضی مباحث که خودم آنها را غیر ضروری فرض کرده بودم برای قبولی در امتحان ۵۳۶ اجباری می‌باشد.

۳- اگر قرار باشد بار دیگر هم کتابی راجع به C#‎ بخوانم احتمالاً این دفعه نگاهی به کتاب C# in Depth بیندازم. آن هم به خاطر ارادت خاصی که نسبت به Jon Skeet پیدا کرده‌ام.

اشتباهات دوران دانشگاه

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

۱- عدم توجه جدی به درس‌های غیر تخصصی خصوصاً دروس ریاضی و فیزیک در دوران دانشگاه.
البته منظورم از توجه این نیست که دروس بی‌استفاده‌ای مثل فیزیک ۱، ریاضی مهندسی، مدار الکتریکی یا معارف را با دقت زیاد خوانده و به خاطر سپرد. بلکه منظورم این است که باید آن‌ها را طوری پاس می‌کردم که کمترین وقت را از من تلف کرده تا بتوانم از وقت آزادم استفاده بهتری ببرم. و الا اعتقاد من این است که در دروسی مثل دروس فوق‌الذکر هیچ چیز با ارزشی برای یک دانشجوی نرم‌افزار وجود نداشته و نخواهد داشت.

۲- شبکه اجتماعی ضعیف
آن وقت‌ها فکر می‌کردم رابطه با بقیه همکلاسی‌ها و هم دانشگاهی‌ها یک دوستی صرف است. اما بعدها که دیدم هیچ لینک درست و حسابی برای پیدا کردن کار مناسب، گذراندن سربازی، انتخاب پروژه فارغ‌التحصیلی و خیلی مسائل دیگر نداشته‌ام فهمیدم که سخت در اشتباه بوده‌ام. البته نه این که دوستی‌ها فقط باید بر اساس منفعت باشد اما باید کمی هم به آینده فکر کرد.

۳- «دو دوره کردن» پروژه فارغ التحصیلی و کارآموزی
«دو دره کردن» اصطلاحی بد معنی است و بیشتر به معنی دزدیدن یا دور زدن و پیچوندن شدید به کار می‌رود. اما متاسفانه من هم مثل تعداد قابل توجهی از بقیه دوستان، پروژه و کارآموزی را با آب بندی و خالی بندی گذارندم. اگر می‌توانستم یک موضوع خوب برای پروژه پیدا کنم و حسابی روی آن وقت بگذارم و اگر یک شرکت خوب برای کارآموزی پیدا کرده و برای آن هم وقت می‌گذاشتم الان وضعیت خیلی بهتری در بازار کار می‌داشتم. متاسفانه پیچوندن در همه دروس و در همه زمینه‌ها در علم و صنعت حسابی باب بود.

۴- انتخاب C#‎ به جای جاوا.
آن اوایل دانشگاه همه ما با هم دلفی کار بودیم اما کمی بعد سر و کله دات‌نت و جاوا پیدا شد و خیلی‌ها از جمله خود من دلفی را فراموش و به سمت یکی از این دو سکو رفتیم. آن زمان خیلی با بحث Open Source و… آشنا نبودم و فکر می‌کردم چون جاوا کد باز است ممکن است خیلی رشد نکند. ولی چون مایکروسافت یک شرکت تجاری خیلی بزرگ است حتماً دات‌نت‎ موفق‌تر خواهد بود. البته گذر زمان نشان داد هر چند که دات‌نت‎ چندان شکست نخورد اما آنهایی که به سمت جاوا رفتند موفق‌تر بودند خصوصاً آنها که در ایران بودند. به عنوان مدرک می‌توانید تعداد پروژه‌های موفق در جاوا را مقایسه کنید با پروژه‌های موفق C#‎. به عنوان مثال Hibernate را. اگر نمونه کدها یا سواد آدم‌های جاوا کار را مقایسه کنید با نمونه کدهای C#‎ یا آدم‌های C#‎ کار متوجه می‌شوید که به طور نسبی جاوا کارها با سوادتر و کدهایی که می‌نویسند دقیق‌تر و اصولی‌تر است. در بازار کار هم برنامه‌نویس‌های جاوا محبوبیت بیشتری داشته و حتی میانگین حقوقی بالاتری هم دارند. به طور کلی به نظر می‌رسد در ایران شرکت‌های جاوایی تیم‌های قوی‌تر و برنامه‌نویس‌های بهتری داشته باشند تا شرکت‌های دات‌نتی.

۵- عدم استفاده مفید از سربازی
هر چند که سربازی را باید رفت چون همه می‌روند اما بنده به خاطری کوتاهی‌هایی که در بعضی زمینه‌ها و شبکه اجتماعی (در اینجا آشنا و پارتی) در طول دوران تحصیل کرده بودم نتوانستم امریه پیدا کنم. حتی نتوانستم در شهر یا نیروی دلخواه به سربازی بروم. در نتیجه دو سال از وقت با ارزشم را در تبریز و کوه‌های لرستان سپری کردم. طی این مدت تنها ارتباطم با کامپیوتر مجموعه Microsoft Office و خواندن یک کتاب ASP بود.

۶- عدم اصرار بر کار شرکتی در حین تحصیل
هر چند که حین تحصیل و خصوصاً اواخر آن چندتایی کار پروژه‌ای به تورم خورد. اما اگر همان کارها را به صورت شرکتی انجام می‌دادم هم موفق‌تر عمل می‌کردم، هم با بازار کار رسمی آشنایی بیشتری پیدا می‌کردم و هم می‌توانستم شبکه اجتماعی‌ام را بیشتر گسترش دهم. این موضوع را بعداً وقتی که با تعداد زیادی از دانشجویان شاغل به صورت پاره وقت مواجه شدم بیشتر درک کردم.

۷- دیگر موارد متفرقه مثل عدم کار روی پروژه‌های کد باز معروف، عدم حضور جدی و موثر در المپیادها، مسابقات و همایش‌های دانشجویی، دوست‌یابی نادرست و…

Partial Class

همیشه فکر می‌کردم امکان Partial Class در مورد کلاس‌هایی که خودم می‌نویسم چیز بی‌استفاده‌ای است. تا این که دیروز شرایطی پیش آمد که فقط Partial Class می‌توانست به من کمک کند.

من یک کلاس حجیم، بیش از ۷۰۰ خط داشتم که کار کردن با آن سخت شده بود. خصوصاً این که چند نفر به طور هم‌زمان روی آن کار می‌کردند و همیشه احتمال بروز conflict موقع check-in وجود داشت. علاوه بر این عملکرد متودهای آن را می‌شد به ۲ یا ۳ بخش مستقل تقسیم‌بندی کرد و بهتر بود هر کدام را در جای مستقلی نگه می‌داشتم. بنابراین فکر کردم که تقسیم این کلاس به دو یا چند کلاس دیگر خیلی بهتر است.

این کلاس از نوع Generic است و بیشتر اعضایش از نوع static تعریف شده‌اند. اول کار این طور به نظرم رسید که از Extension Method استفاده کرده و بخش‌های دوم و سوم را به یک کلاس static دیگر برده و عملکرد آنها را از طریق Extension Method مورد استفاده قرار دهم. با این که Extension Methodها با کلاس‌های Generic مشکلی نداشتند، اما چون می‌خواستم از داخل Extension Methodها، متودهای کلاس اصلی را که از نوع static هم بودن را صدا بزنم دچار خطای زیر می‌شدم:

Member ‘SomeMethod()’ cannot be accessed with an instance reference; qualify it with a type name instead

علت خطا همان طور که مشخص است این است که من اجازه ندارم از داخل Extension Methodها، متودهای static را صدا بزنم. ظاهراً دلیل آن این است که با Extension Methodها مشابه متودهای غیر static برخورد می‌شود و فراخوانی متودهای static از داخل آنها ممنوع است.

در اینجا بود که استفاده از Partial Classها به دردم خورد: کلاس مورد نظرم را به چند بخش کوتاه‌تر که از لحاظ عملکرد به هم شبیه بودند تقسیم کردم. این طوری اقلاً حجم فایل کلاس کوتاه‌تر شده و کار تیمی با آن راحت‌تر شد. به مثال MSDN دقت کنید:

public partial class Employee
{
public void DoWork()
{
}
}

public partial class Employee
{
public void GoToLunch()
{
}
}

Create simple CodeActivity for TFS Build 2010

Sometimes that you need to customize TFS Build 2010, you need to create a custom CodeActivity. A CodeActivity is written in C# and you can do what you can’t in TFS Build itself, there. The simplest way to create a custom CodeActivity, deploy and use it, is as follow:

1. Create a .Net 4.0 based Class Library project. CodeActivity exists in .Net framework 4.0 only.

2. Add a Code Activity to it by right click on the project, select Add New Item and navigating to Workflow tab.

3. Add a reference to “C:Program Files (x86)Microsoft Visual Studio 10.0Common7IDEReferenceAssembliesv2.0Microsoft.TeamFoundation.Build.Client.dll”.

4. Add “[BuildActivity(HostEnvironmentOption.All)]” as your CodeActivity’s class attribute.

5. Add desired arguments and codes.

6. Build the project.

7. Copy generated dll to “C:Program Files (x86)Microsoft Visual Studio 10.0Common7IDEPrivateAssemblies”. If you don’t do this, you will not be able to use Visual Studio to add your CodeActivity to any build process template.

8. Add generated dll to a specific location in TFS Source Control.

9. Open up your desired build process template.

10. Add generated dll to the toolbox by right clicking on empty space in General tab, select “Choose Items…”, click Browse, navigate to “C:Program Files (x86)Microsoft Visual Studio 10.0Common7IDEPrivateAssemblies” again and select your generated dll. After this you will see your CodeActivity there.

11. Drag Code Activity on the desired placed in process template.

12. Add any arguments that you want to be accessed via Build Definition to the template process and pass them to your CodeActivity’s arguments. To add any arguments to a template process, open Arguments tab in the bottom-left corner of the screen and add them there.

13. Check-in template process. If you don’t so, you will not see your added arguments in Process tab of build definitions.

14. Open Build Definition that uses this build process template. You will see any arguments that you have previously added to build process. You can set any value in them.

Note: Above addresses are based on a x64 installation.
Note: For more info refer to Jim’s guide and Ewald’s guide.

‫تبدیل به استرینگ در C#‎

اگر شما هم تا حالا برای ساخت یک استرینگ از استرینگ و عدد در C#‎ از روشی مثل string str = “old” + (2+2).ToString()‎ استفاده می‌کردید، یعنی خودتان زحمت ToString()‎ را می‌کشیدید، دیگر این زحمت را نکشید. چون قانون String Concatenation در C#‎، شرح داده شده در بخش ۷.۸.۴ مشخصات زبانی C#‎، طوری است که اگر بخواهید یک عدد یا هر نوع داده‌ای دیگری مثل DateTime یا کلاس‌های ساخت دست خودتان را به یک استرینگ اضافه کنید، آن عدد یا نوع داده‌ای غیر استرینگ خود به خود به استرینگ تبدیل می‌شود، یعنی .ToString()‎ آن به طور خودکار فراخوانی می‌شود.

این موضوع را وسط یک رفتار عجیب C#‎ پیدا کردم. یک سری کد از قبل داشتم که در آنها یک رشته به یک متغیر از نوع استرینگ می‌چسبید. نوع آن متغیر را بعد از مدتی به یک کلاس ساخت خودم تبدیل کردم و انتظار داشتم کامپایلر C#‎ به آن خط گیر بدهد که نداد. به همین خاطر یک سوال در Stack Overflow پرسیدم و علت را فهمیدم.

Implementing History model

In many applications, data change is tracked. For example in TFS whenever you change any section of a work item, you can then see that change has been logged in work item history. It says that, for instance, owner of work item or time estimation field has been changed from a value to another value. Another example is article history in Wikipedia. Both TFS and Wikipedia are large applications. So what should you do if you want to add history feature for a small or medium application? Suppose your application have 20 domain classes (tables) that all of them needs to keep tracking of changes. Is it a good idea to add an extra class/table for each of them to save their history? Is there any other way?

As a solution I used a simple way: having a single class/table as main history repository, using Xml Serialization for persisting changes and Reflection to explore field changes. This way you need to use two events of your ORM: AfterLoad and OnSave or something similar. You must serialize objects in AfterLoad as old (current) value, serialize each object in OnSave as new value, saving in database and consequently showing data change by deserializing them and using Reflection to explore changes. This way has a large overload as a very long record will be saved in database with each change in data, but if history feature is forced to be done then it is a concise and centralized solution. Specially when compared to ways that developer must save history manually by adding code to each UI section that modifies data.

Using NHibernate event model in Castle ActiveRecord

Castle ActiveRecord is a thin layer over NHibernate and provides easy and fast use of NHibernate. Regarding data save/retrieve in Castle ActiveRecord, there is some useful events like OnSave and OnUpdate that can be utilized to automate features like automatic data tracing or data auditing. Unfortunately there is situations that we need events that are not supported directly in Castle ActiveRecord. For example we need an event like AfterLoad or PostLoad in order to do some specific operations in our application. But Castle ActiveRecord didn’t provide us with such an event. Googling showed me that I can leverage NHibernate events to achieve this goal. But how can I catch firing of NHibernate’s events in Castle ActiveRecord? This was not an easy question to be googled. BTW asking in StackOverflow and some extra googling here and here showed me the way.

Listening to NHibernate events in Castle ActiveRecord was very easier than I thought. All you must do is creating a class that implements a special interface and add a special attribute in class file. That’s it. You are done! No need to modify web.config or add code when initializing Castle ActiveRecord. So here is my listener class:

using Castle.ActiveRecord.Attributes;
using NHibernate.Event;

[assembly: AddEventListener(typeof(MyNameSpace.MyPostLoadEventListener))]

namespace MyNameSpace
{
    public class MyPostLoadEventListener : IPostLoadEventListener
    {
        public void OnPostLoad(PostLoadEvent @event)
        {
            //do what ever you want with @event.
        }
    }
}

امتحان ورود کارشناسی ارشد

روز جمعه ۲۹ مرداد ۸۹ امتحان ورودی کارشناسی ارشد ناپیوسته مهندسی فن‌آوری اطلاعات دانشکده آموزش‌های الکترونیک دانشگاه شیراز در محل موسسه آیین زندگی حوالی آریاشهر برگزار شد. امتحان گرایش طراحی و تولید نرم‌افزار شامل سوالاتی از دروس زبان، ریاضی، برنامه‌سازی و مهندسی نرم‌افزار بود. صرف نظر از ایردات معمول امتحان، می‌توان ایراداتی را هم به سولات دو درس برنامه‌سازی پیشرفته و مهندسی نرم‌افزار وارد کرد.

۱- زبان برنامه‌نویسی مورد استفاده جاوا بود و آن‌هایی که مثل من به جای جاوا، سی‌شارپ بلد بودند خیلی متضرر شدند. البته این موضوع از قبل هم اعلام شده بود ولی اعلام قبلی آن فرق آنچنانی در اصل موضوع ایجاد نمی‌کرد.

۲- سوال ۳۳ کاملاً اشتباه بود. کد داده شده وارد حلقه بی‌نهایت می‌شد و البته هیچ کدام از خروجی‌های داده شده در گزینه‌های داده شده را تولید نمی‌کرد. به اصل سوال و گزینه‌های آن دقت کنید:

Public class test {
Public static void main(String[] args)
{
for (int j=1; j<=5; j++) {
for (int k=1; j<=j; k++)
System.out.print('*');
System.out.println();
}
}
}

گزینه اول
*****
****
***
**
*
گزینه دوم
*****
****
***
**
*
گزینه سوم
*
**
***
****
*****
گزینه چهارم
*
**
***
****
*****

البته اگر شرط حلقه دوم را با k<=j عوض کنیم مشکل حل شده و گزینه چهار صحیح خواهد بود.

۳- یک سوال سه بار تکرار شده بود! سوالات ۵۰ و ۵۴ کاملاً یکی بودند و سوال ۵۶ هم همان سوال ۵۰ و ۵۴ بود که فقط کمی متن آن عوض شده و جای دو تا از گزینه‌ها عوض شده بود. سوال عبارت بود از «کدام یک از موارد زیر در طراحی مورد بررسی قرار نمی‌گیرد.»

۴- در بعض از سوال‌ها از معادل‌های فارسی نامأنوسی استفاده بود که جواب دادن به سوالات را بی‌دلیل سخت می‌کرد. از جمله «واسط» به جای interface در سوال ۵۶، «تغییر دهنده» به معنی کلمات public و private که در ابتدای تعریف متودها و دیگر اعضای کلاس‌ها می‌آید.

۵- اشتباهات تایپی و گرامری هم که نایاب نبودند. مثلاً به گنگی سوال ۵۷ دقت کنید: «همبستگی (cohesion) یک نمایان کیفی است از میزان درجه این که یک ماژول …» گزینه اول: بتواند به صورت فشرده‌تر نوشته شود. گزینه دوم…

من البته هیچ وقت به جاوا برنامه ننوشته‌ام ولی حدس می‌زنم اگر یک برنامه‌نویس جاوا در این امتحان شرکت می‌کرد سوتی‌های دیگری هم را پیدا می‌کرد.

Saving time as UTC with NHibernate

In many applications that have world wide users, there is a need to dealing with UTC. In these applications, time is stored in UTC and then showed backed in local time to users. A good solution is not to bother developers to convert time to universal or local time every time manipulating time related data. Instead we could add a bit of code to setter getter of DateTime fields. Unfortunately this solution does not work in NHibernate and possibly other ORMs. Consider following code:

DateTime _myDate;

[Property]
public virtual DateTime MyDate
{
    set { _myDate = value;}
    get {return _myDate;}
}

In this code we can not add a ToLocalTime() or ToUniversalTime() to setter or getter. Because both NHibernate and the application use this same getter and setter. Real solution is to use a helper field. This way the helper field will not persist on database but real field persists on database. Real field mus not be accessible to developer because of confusion and possible unwanted changes. Consider final solution:

public virtual DateTime MyDate //helper field
{
    set { MyDateUtc = value.ToUniversalTime(); }
    get { return MyDateUtc.ToLocalTime(); }
}

[Property]
private DateTime MyDateUtc { set; get; } //real field

All codes are based on Castle Active Record.