سری پویانمایی در AngularJS
معرفی سایت ng-nuggets
AngularJS #2
استفاده از اپراتور is به همراه pattern matching
اپراتور is از اولین نگارش #C مهیا بودهاست و هدف آن بررسی تطابق شیءایی خاص، با نوعی مفروض است. برای مثال آیا این نوع مورد بررسی، اینترفیس خاصی را پیاده سازی میکند و یا اینکه آیا از کلاسی خاص مشتق شدهاست یا خیر؟ حاصل این بررسی هم true یا false است.
با بهبودهای حاصل شدهی در C# 7، اکنون میتوان از اپراتور is جهت بررسی الگوها نیز استفاده کرد.
الگوی const
در مثال ذیل، آرایهای از اشیاء، شامل یک نال، یک عدد و دو شیء کاربر، تعریف شدهاند:
public class User { public User(string name) { Name = name; } public string Name { get; } } object[] data = { null, 42, new User("User 1"), new User("User 2") }; foreach (var item in data) { if (item is null) Console.WriteLine("it's a const pattern"); if (item is 42) Console.WriteLine("it's 42"); }
در C# 7 میتوان اپراتور is را بر روی یک عدد ثابت مانند 42 و یا یک null بکار گرفت. پیش از C# 7 برای بررسی نال بودن یک شیء، تنها از پراتور == میشد استفاده کرد.
الگوی Type
دومین الگوی مهیای در C# 7، «الگوی نوع» نام دارد و هدف آن بررسی تطابق یک شیء، با شیءایی دیگر است. مهمترین تفاوت آن با نگارشهای پیشین سی شارپ این است که اگر اکنون تطابقی تشخیص داده شود، شیء، به متغیر جدید تعریف شده، انتساب داده میشود:
object[] data = { null, 42, new User("User 1"), new User("User 2") }; foreach (var item in data) { if (item is int i) Console.WriteLine($"it's a type pattern with an int and the value {i}"); if (item is User p) Console.WriteLine($"it's a person: {p.Name}"); if (item is User p2 && p2.Name.StartsWith("U")) { Console.WriteLine($"it's a person starting with U {p2.Name}"); } }
و یا اکنون قطعه کد قدیمی ذیل را
object obj1 = "Hello, World!"; var str1 = obj1 as string; if (str1 != null) { Console.WriteLine(str1); }
object obj2 = "Hello, World!"; if (obj2 is string str2) { Console.WriteLine(str2); }
الگوی Var
سومین الگوی مهیای در C# 7، الگوی var نام دارد و در این حالت میتوان بجای ذکر صریح نوع تطابق داده شده، از var استفاده کرد.
بدیهی است این الگو همواره با موفقیت روبرو میشود؛ چون var به همان نوع شیء مفروض اشاره میکند:
object[] data = { null, 42, new User("User 1"), new User("User 2") }; foreach (var item in data) { if (item is var x) Console.WriteLine($"it's a var pattern with the type {x?.GetType()?.Name}"); }
در این حالت اگر item دقیقا null باشد، برای بررسی آن میتوان از null conditional operator معرفی شدهی در C# 6 استفاده کرد.
استفاده از عبارت switch به همراه pattern matching
در C# 7، عبارت switch نیز تکامل یافتهاست. در اینجا الگوهای const ،var و type را نیز میتوان پس از ذکر case بکار گرفت:
public static void SwitchPattern(object o) { switch (o) { case null: Console.WriteLine("it's a constant pattern"); break; case int i: Console.WriteLine("it's an int"); break; case User p when p.Name.StartsWith("U"): Console.WriteLine($"a U person {p.Name}"); break; case User p: Console.WriteLine($"any other person {p.Name}"); break; case var x: Console.WriteLine($"it's a var pattern with the type {x?.GetType().Name} "); break; default: break; } }
تنها نکتهی جدید در اینجا، استفاده از واژهی کلیدی when است برای ترکیب شرطها (case User p when p.Name.StartsWith). بنابراین در C# 7 امکان نوشتن case null میسر است؛ به همراه نوشتن شرطها توسط when، در حین تعاریف caseها. به علاوه اینبار عبارت switch محدود به نوعهای پایه مانند اعداد، رشتهها و enums نیست و در اینجا میتوان یک شیء را نیز مشخص کرد.
شبیه سازی switch موجود در ویژوال بیسیک در C# 7
ویژوال بیسیک از نگارشهای ابتدایی آن دارای caseهای پیشرفتهتری است نسبت به #C. برای نمونه در اینجا امکان تعریف تعدادی عدد، استفاده از To و استفادهی از =< را هم مشاهده میکنید:
Select Case age Case 50 ageBlock = "the big five-oh" Case 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 ageBlock = "octogenarian" Case 90 To 99 ageBlock = "nonagenarian" Case Is >= 100 ageBlock = "centenarian" Case Else ageBlock = "just old" End Select
اکنون در C# 7 میتوان یک چنین توانمندی را با pattern matching هم پیاده سازی کرد:
string ageBlock; var age = 40; switch (age) { case 50: ageBlock = "the big five-oh"; break; case var testAge when (new List<int> { 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 }).Contains(testAge): ageBlock = "octogenarian"; break; case var testAge when ((testAge >= 90) && (testAge <= 99)): ageBlock = "nonagenarian"; break; case var testAge when (testAge >= 100): ageBlock = "centenarian"; break; default: ageBlock = "just old"; break; }
همانطور که مشاهده میکنید، در قسمت when نیز میتوان توسط && و || نیز شرطها را ترکیب کرد و یا متدی را با خروجی bool (مانند Contains) بر روی مقدار دریافتی اعمال کرد.
نمایش متن در زیر جدول مربوط به هر گروه
.MainTableEvents(events => { #region ShowEblaghDescription if (ShowEblaghDescription) { events.GroupAdded(args=> { var infoTable = new PdfGrid(numColumns: 1) { SpacingBefore = 0, HorizontalAlignment = 0, WidthPercentage = 100, RunDirection = PdfWriter.RUN_DIRECTION_RTL, }; infoTable.AddCell(new PdfPCell() { BorderWidthTop = 1, BorderWidthBottom = 0, BorderWidthLeft = 0, BorderWidthRight = 0, HorizontalAlignment = 0, VerticalAlignment = 1, Phrase = new Phrase(ReportParameter.EblaghDescription, FontHelper.GetFont(FarsiFont.Zar, 12, false, BaseColor.BLACK)), RunDirection = PdfWriter.RUN_DIRECTION_RTL, }); args.PdfDoc.Add(infoTable); }); ...
«Splashdata، توسعه دهنده نرم افزارهای امنیتی، فهرست سالانه خود را از رایجترین رمزهای عبور منتشر کرده است.»
میشود از این لیست برای بهبود پروسه ثبت نام در یک سایت استفاده کرد و همان زمان که کاربر کلمه عبور ضعیفی را وارد کرده است، به او پیغام داد که «کلمه عبور وارد شده را راحت میتوان حدس زد!»
using System.Linq; namespace SecurityModule { public static class SafePassword { public static ISet<string> BadPasswords = new HashSet<string> { "password", "password1", "123456", "12345678", "1234", "qwerty", "12345", "dragon", "******", "baseball", "football", "letmein", "monkey", "696969", "abc123", "mustang", "michael", "shadow", "master", "jennifer", "111111", "2000", "jordan", "superman", "harley", "1234567", "iloveyou", "trustno1", "sunshine", "123123", "welcome" }; public static bool IsSafePasword(this string data) { if (string.IsNullOrWhiteSpace(data)) return false; if (data.Length < 5) return false; if (BadPasswords.Contains(data.ToLowerInvariant())) return false; if (data.AreAllCharsEuqal()) return false; return true; } public static bool AreAllCharsEuqal(this string data) { if (string.IsNullOrWhiteSpace(data)) return false; data = data.ToLowerInvariant(); var firstElement = data.ElementAt(0); var euqalCharsLen = data.ToCharArray().Count(x => x == firstElement); if (euqalCharsLen == data.Length) return true; return false; } } }
- خالی نیست.
- بیشتر از 5 کاراکتر طول دارد.
- تمام حروف بکارگرفته شده در آن یکسان نیستند.
و در ASP.NET MVC با استفاده از قابلیت Remote validation آن استفاده از این متد به نحو زیر خواهد بود:
public partial class RegisterController : Controller { //... [HttpPost] [OutputCache(Location = OutputCacheLocation.None, NoStore = true)] public virtual ActionResult CheckPassword(string password1) { return Json(password1.IsSafePasword()); } }
سپس قسمتی از ViewModel متناظر با صفحه ثبت نام سایت، به شکل زیر اضافه و تعریف میگردد:
using System.ComponentModel.DataAnnotations; using System.Web.Mvc; namespace MyBlog.Models { public class RegisterViewModel { //... [Display(Name = "کلمه عبور")] [Required(ErrorMessage = "لطفا کلمه عبور خود را وارد نمائید")] [DataType(DataType.Password)] [StringLength(50, MinimumLength = 5, ErrorMessage = "حداقل طول کلمه عبور 5 حرف است")] [Remote(action: "CheckPassword", controller: "Register", HttpMethod = "POST", ErrorMessage = "کلمه عبور وارد شده را راحت میتوان حدس زد!")] public string Password1 { get; set; } } }
$("#list").trigger("reloadGrid");
ترجیحا نوع Typescript را انتخاب کردم. البته در داخل فایل ts. امکان نوشتن جاوا اسکریپت هم هست. بعد از ایجاد پروژه اگر با تصویری شبیه به تصویر زیر روبرو شدید، در نتیجه تنظیمات نصب و راه اندازی به درستی صورت گرفته است.
اگر به قسمت solution explorer دقت کنید، فایلی به نام config.xml را مشاهده خواهید کرد. با کلیک بر روی این فایل، یک صفحهی گرافیکی باز خواهد شد که این امکان را به شما میدهد که پلاگینهای مورد نیاز خود، تنظیمات مربوط به نرم افزار تولیدی (مانند تنظیم ورژن ویندوزی که میخواهید app شما بر روی آن اجرا شود) و تنظیمات مربوط به هر یک از پلتفرمها را به صورت مجزا در اختیار داشته باشید.
یک فایل index.html هم در قالب پیشفرض قرار داده شده که بعدا میتوانید آن را تغییر دهید و یا صفحات دیگری را اضافه کنید. همان طور که در قسمتهای قبل گفته شد، قرار است ما یک وب اپلیکیشن طراحی کنیم و آن را درون Container بومی Cordova بسته بندی کنیم. لذا محدودیتی برای استفادهی از کتابخانههای مرتبط با CSS ، HTML و JavaScript نداریم و در ادامهی مقالات با مثالهای متعددی از آنها استفاده خواهیم کرد.
در فولدر scripts-->typeings-->cordova-->plugins اینترفیسهایی که برای دسترسی به امکانات بومی دستگاه تلفن فعلا در Cordova پشتیبانی میشوند، قرار گرفته است.
برای استفاده از تکنولوژیهای وب در محیط بومی دستگاه، در طی فرآیند کامپایل، Cordova یک اپلیکیشن را به وسیله دو چیز مهم که در زیر اشاره شده است، خواهد ساخت.
- یک اپلیکیشن با یک کامپوننت WebView که با مرورگر یکپارچه شده است.
- یه سری از منابعی که در داخل فایلهای اپلیکیشن وب ما قرار دارند.
برای یکپارچه شدن APIهای Cordova با وب پیج موجود، اندکی کد نیاز داریم که برای انکار لینکی شبیه لینک زیر را در فایل html خود استفاده میکنیم که فقط بعد از کامپایل وجود خارجی دارد؛ به صورت زیر:
<script src="cordova.js"></script>
در پایان هم برای فهمیدن اینکه APIهای Cordova در دسترس هستند، میتوانیم رخداد مربوط به devicerady را مدیریت کنیم؛ به صورت زیر:
document.addEventListener("deviceready", onDeviceReady, false); function onDeviceReady() { /* INIT */ }
برای مدیریت رخدادهای مربوط به pause و resume هم که نشان دهندهی ادامه برنامه (خارج شدن از حالت pause) و حالت تعلیق هستند، میتوان به شکل زیر عمل کرد:
function onDeviceReady() { // Handle the Cordova pause and resume events document.addEventListener('pause', onPause, false); document.addEventListener('resume', onResume, false); // TODO: Cordova has been loaded. Perform any initialization that requires Cordova here. } function onPause() { // TODO: This application has been suspended. Save application state here. } function onResume() { // TODO: This application has been reactivated. Restore application state here. }
حال قصد داریم پروژهی خود را که قرار است یک متن ساده را نشان دهد، با استفاده از شبیه ساز اجر ا کنیم. برای این منظور از قسمت toolbar ویژوال استودیو ، Solution Platform خود را انتخاب کنید و سپس میتوانید شبیه ساز مورد نظر خود را انتخاب کرده و برنامه را اجرا کنید. در اینجا محیط مورد نظر من اندروید است و برای این منظور هم میتوانم از شبیه ساز Android Emulator یا Ripple استفاده کنم. به دلیل سرعت کم شبیه ساز اندروید، میتوانید شبیه ساز YouWave را دانلود و اجرا کرده و در قسمتی که شبیه ساز را از toolbar ویژوال انتخاب میکردید، این بار گزینهی Device را انتخاب کنید. بعد از کامپایل برنامهی شما، فایل apk تولید شده بر روی شبیه ساز نصب خواهد شد و شما قادر خواهید بود آنرا اجرا کنید.
نتیجهی نهایی
با شبیه ساز Ripple
مطالعه بیشتر
https://msdn.microsoft.com/en-us/library/dn879821(v=vs.140).aspx
http://blog.falafel.com/getting-started-with-cordova-and-multi-device-hybrid-app-in-visual-studio/
http://www.codeproject.com/Articles/860150/Visual-Studio-and-Apache-Cordova
نکته : وقتی پروژه را برای اولین بار اجرا میکنید شاید کمی طول بکشد تا نتیجهی نهایی را ببنید و آن هم به دلیل این است که ویژوال استودیو باید مجموعهای از package های مورد نیاز Cordova را دانلود کند.
در مقاله بعد با jQuery Mobile آشنا خواهیم شد و یک مثال برای کار کردن با آن در نظر خواهم گرفت.
ادامه دارد ...
آشنایی با Automapping در فریم ورک Fluent NHibernate
اگر قسمتهای قبل را دنبال کرده باشید، احتمالا به پروسه طولانی ساخت نگاشتها توجه کردهاید. با کمک فریم ورک Fluent NHibernate میتوان پروسه نگاشت domain model خود را به data model متناظر آن به صورت خودکار نیز انجام داد و قسمت عمدهای از کار به این صورت حذف خواهد شد. (این مورد یکی از تفاوتهای مهم NHibernate با نمونههای مشابهی است که مایکروسافت تا تاریخ نگارش این مقاله ارائه داده است. برای مثال در نگارشهای فعلی LINQ to SQL یا Entity framework ، اول دیتابیس مطرح است و بعد ساخت کد از روی آن، در حالیکه در اینجا ابتدا کد و طراحی سیستم مطرح است و بعد نگاشت آن به سیستم دادهای و دیتابیس)
امروز قصد داریم یک سیستم ساده ثبت خبر را از صفر با NHibernate پیاده سازی کنیم و همچنین مروری داشته باشیم بر قسمتهای قبلی.
مطابق کلاس دیاگرام فوق، این سیستم از سه کلاس خبر، کاربر ثبت کنندهی خبر و گروه خبری مربوطه تشکیل شده است.
ابتدا یک پروژه کنسول جدید را به نام NHSample2 آغاز کنید. سپس ارجاعاتی را به اسمبلیهای زیر به آن اضافه نمائید:
FluentNHibernate.dll
NHibernate.dll
NHibernate.ByteCode.Castle.dll
NHibernate.Linq.dll
و ارجاعی به اسمبلی استاندارد System.Data.Services.dll دات نت فریم ورک سه و نیم
سپس پوشهای را به نام Domain به این پروژه اضافه نمائید (کلیک راست روی نام پروژه در VS.Net و سپس مراجعه به منوی Add->New folder). در این پوشه تعاریف موجودیتهای برنامه را قرار خواهیم داد. سه کلاس جدید Category ، User و News را در این پوشه ایجاد نمائید. محتویات این سه کلاس به شرح زیر هستند:
namespace NHSample2.Domain
{
public class User
{
public virtual int Id { get; set; }
public virtual string UserName { get; set; }
public virtual string Password { get; set; }
}
}
namespace NHSample2.Domain
{
public class Category
{
public virtual int Id { get; set; }
public virtual string CategoryName { get; set; }
}
}
using System;
namespace NHSample2.Domain
{
public class News
{
public virtual Guid Id { get; set; }
public virtual string Subject { get; set; }
public virtual string NewsText { get; set; }
public virtual DateTime DateEntered { get; set; }
public virtual Category Category { get; set; }
public virtual User User { get; set; }
}
}
اکنون کلاس جدید Config را به برنامه اضافه نمائید:
using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
namespace NHSample2
{
class Config
{
public static Configuration GenerateMapping(IPersistenceConfigurer dbType)
{
var cfg = dbType.ConfigureProperties(new Configuration());
new AutoPersistenceModel()
.Where(x => x.Namespace.EndsWith("Domain"))
.AddEntityAssembly(typeof(NHSample2.Domain.News).Assembly).Configure(cfg);
return cfg;
}
public static void GenerateDbScript(Configuration config, string filePath)
{
bool script = true;//فقط اسکریپت دیتابیس تولید گردد
bool export = false;//نیازی نیست بر روی دیتابیس هم اجرا شود
new SchemaExport(config).SetOutputFile(filePath).Create(script, export);
}
public static void BuildDbSchema(Configuration config)
{
bool script = false;//آیا خروجی در کنسول هم نمایش داده شود
bool export = true;//آیا بر روی دیتابیس هم اجرا شود
bool drop = false;//آیا اطلاعات موجود دراپ شوند
new SchemaExport(config).Execute(script, export, drop);
}
public static void CreateSQL2008DbPlusScript(string connectionString, string filePath)
{
Configuration cfg =
GenerateMapping(
MsSqlConfiguration
.MsSql2008
.ConnectionString(connectionString)
.ShowSql()
);
GenerateDbScript(cfg, filePath);
BuildDbSchema(cfg);
}
public static ISessionFactory CreateSessionFactory(IPersistenceConfigurer dbType)
{
return
Fluently.Configure().Database(dbType)
.Mappings(m => m.AutoMappings
.Add(
new AutoPersistenceModel()
.Where(x => x.Namespace.EndsWith("Domain"))
.AddEntityAssembly(typeof(NHSample2.Domain.News).Assembly))
)
.BuildSessionFactory();
}
}
}
در متد GenerateMapping از قابلیت Automapping موجود در فریم ورک Fluent Nhibernate استفاده شده است (بدون نوشتن حتی یک سطر جهت تعریف این نگاشتها). این متد نوع دیتابیس مورد نظر را جهت ساخت تنظیمات خود دریافت میکند. سپس با کمک کلاس AutoPersistenceModel این فریم ورک، به صورت خودکار از اسمبلی برنامه نگاشتهای لازم را به کلاسهای موجود در پوشه Domain ما اضافه میکند (مرسوم است که این پوشه در یک پروژه Class library مجزا تعریف شود که در این برنامه جهت سهولت کار در خود برنامه قرار گرفته است). قسمت Where ذکر شده به این جهت معرفی گردیده است تا Fluent Nhibernate برای تمامی کلاسهای موجود در اسمبلی جاری، سعی در تعریف نگاشتهای لازم نکند. این نگاشتها تنها به کلاسهای موجود در پوشه دومین ما محدود شدهاند.
سه متد بعدی آن، جهت ایجاد اسکریپت دیتابیس از روی این نگاشتهای تعریف شده و سپس اجرای این اسکریپت بر روی دیتابیس جاری معرفی شده، تهیه شدهاند. برای مثال CreateSQL2008DbPlusScript یک مثال ساده از استفاده دو متد قبلی جهت ایجاد اسکریپت و دیتابیس متناظر اس کیوال سرور 2008 بر اساس نگاشتهای برنامه است.
با متد CreateSessionFactory در قسمتهای قبل آشنا شدهاید. تنها تفاوت آن در این قسمت، استفاده از کلاس AutoPersistenceModel جهت تولید خودکار نگاشتها است.
در ادامه دیتابیس متناظر با موجودیتهای برنامه را ایجاد خواهیم کرد:
using System;
namespace NHSample2
{
class Program
{
static void Main(string[] args)
{
Config.CreateSQL2008DbPlusScript(
"Data Source=(local);Initial Catalog=HelloNHibernate;Integrated Security = true",
"db.sql");
Console.WriteLine("Press a key...");
Console.ReadKey();
}
}
}
پس از اجرای برنامه، ابتدا فایل اسکریپت دیتابیس به نام db.sql در پوشه اجرایی برنامه تشکیل خواهد شد و سپس این اسکریپت به صورت خودکار بر روی دیتابیس معرفی شده اجرا میگردد. دیتابیس دیاگرام حاصل را در شکل زیر میتوانید ملاحظه نمائید:
همچنین اسکریپت تولید شده آن، صرفنظر از عبارات drop اولیه، به صورت زیر است:
create table [Category] (
Id INT IDENTITY NOT NULL,
CategoryName NVARCHAR(255) null,
primary key (Id)
)
create table [User] (
Id INT IDENTITY NOT NULL,
UserName NVARCHAR(255) null,
Password NVARCHAR(255) null,
primary key (Id)
)
create table [News] (
Id UNIQUEIDENTIFIER not null,
Subject NVARCHAR(255) null,
NewsText NVARCHAR(255) null,
DateEntered DATETIME null,
Category_id INT null,
User_id INT null,
primary key (Id)
)
alter table [News]
add constraint FKE660F9E1C9CF79
foreign key (Category_id)
references [Category]
alter table [News]
add constraint FKE660F95C1A3C92
foreign key (User_id)
references [User]
اکنون یک سری گروه خبری، کاربر و خبر را به دیتابیس خواهیم افزود:
using System;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHSample2.Domain;
namespace NHSample2
{
class Program
{
static void Main(string[] args)
{
using (ISessionFactory sessionFactory = Config.CreateSessionFactory(
MsSqlConfiguration
.MsSql2008
.ConnectionString("Data Source=(local);Initial Catalog=HelloNHibernate;Integrated Security = true")
.ShowSql()
))
{
using (ISession session = sessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
//با توجه به کلیدهای خارجی تعریف شده ابتدا باید گروهها را اضافه کرد
Category ca = new Category() { CategoryName = "Sport" };
session.Save(ca);
Category ca2 = new Category() { CategoryName = "IT" };
session.Save(ca2);
Category ca3 = new Category() { CategoryName = "Business" };
session.Save(ca3);
//سپس یک کاربر را به دیتابیس اضافه میکنیم
User u = new User() { Password = "123$5@1", UserName = "VahidNasiri" };
session.Save(u);
//اکنون میتوان یک خبر جدید را ثبت کرد
News news = new News()
{
Category = ca,
User = u,
DateEntered = DateTime.Now,
Id = Guid.NewGuid(),
NewsText = "متن خبر جدید",
Subject = "عنوانی دلخواه"
};
session.Save(news);
transaction.Commit(); //پایان تراکنش
}
}
}
Console.WriteLine("Press a key...");
Console.ReadKey();
}
}
}
و یا میتوان از LINQ استفاده کرد:
برای مثال کاربر VahidNasiri تعریف شده را یافته، اطلاعات آنرا نمایش دهید؛ سپس نام او را به Vahid ویرایش کرده و دیتابیس را به روز کنید.
برای اینکه کوئریهای LINQ ما شبیه به LINQ to SQL شوند، کلاس NewsContext را به صورت ذیل تشکیل میدهیم. این کلاس از کلاس پایه NHibernateContext مشتق شده و سپس به ازای تمام موجودیتهای برنامه، یک متد از نوع IOrderedQueryable را تشکیل خواهیم داد.
using System.Linq;
using NHibernate;
using NHibernate.Linq;
using NHSample2.Domain;
namespace NHSample2
{
class NewsContext : NHibernateContext
{
public NewsContext(ISession session)
: base(session)
{ }
public IOrderedQueryable<News> News
{
get { return Session.Linq<News>(); }
}
public IOrderedQueryable<Category> Categories
{
get { return Session.Linq<Category>(); }
}
public IOrderedQueryable<User> Users
{
get { return Session.Linq<User>(); }
}
}
}
using System;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using System.Linq;
using NHSample2.Domain;
namespace NHSample2
{
class Program
{
static void Main(string[] args)
{
using (ISessionFactory sessionFactory = Config.CreateSessionFactory(
MsSqlConfiguration
.MsSql2008
.ConnectionString("Data Source=(local);Initial Catalog=HelloNHibernate;Integrated Security = true")
.ShowSql()
))
{
using (ISession session = sessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
using (NewsContext db = new NewsContext(session))
{
var query = from x in db.Users
where x.UserName == "VahidNasiri"
select x;
//اگر چیزی یافت شد
if (query.Any())
{
User vahid = query.First();
//نمایش اطلاعات کاربر
Console.WriteLine("Id: {0}, UserName: {0}", vahid.Id, vahid.UserName);
//به روز رسانی نام کاربر
vahid.UserName = "Vahid";
session.Update(vahid);
transaction.Commit(); //پایان تراکنش
}
}
}
}
}
Console.WriteLine("Press a key...");
Console.ReadKey();
}
}
}
اگر به اسکریپت دیتابیس تولید شده دقت کرده باشید، عملیات AutoMapping یک سری پیش فرضهایی را اعمال کرده است. برای مثال فیلد Id را از نوع identity و به صورت کلید تعریف کرده، یا رشتهها را به صورت nvarchar با طول 255 ایجاد نموده است. امکان سفارشی سازی این موارد نیز وجود دارد.
مثال:
using FluentNHibernate.Conventions.Helpers;
public static Configuration GenerateMapping(IPersistenceConfigurer dbType)
{
var cfg = dbType.ConfigureProperties(new Configuration());
new AutoPersistenceModel()
.Conventions.Add()
.Where(x => x.Namespace.EndsWith("Domain"))
.Conventions.Add(
PrimaryKey.Name.Is(x => "ID"),
DefaultLazy.Always(),
ForeignKey.EndsWith("ID"),
Table.Is(t => "tbl" + t.EntityType.Name)
)
.AddEntityAssembly(typeof(NHSample2.Domain.News).Assembly)
.Configure(cfg);
return cfg;
}
تابع GenerateMapping معرفی شده را اینجا با قسمت Conventions.Add تکمیل کردهایم. به این صورت دقیقا مشخص شده است که فیلدهایی با نام ID باید primary key در نظر گرفته شوند، همواره lazy loading صورت گیرد و نام کلید خارجی به ID ختم شود. همچنین نام جداول با tbl شروع گردد.
روش دیگری نیز برای معرفی این قرار دادها و پیش فرضها وجود دارد. فرض کنید میخواهیم طول رشته پیش فرض را از 255 به 500 تغییر دهیم. برای اینکار باید اینترفیس IPropertyConvention را پیاده سازی کرد:
using FluentNHibernate.Conventions;
using FluentNHibernate.Conventions.Instances;
namespace NHSample2.Conventions
{
class MyStringLengthConvention : IPropertyConvention
{
public void Apply(IPropertyInstance instance)
{
instance.Length(500);
}
}
}
public static Configuration GenerateMapping(IPersistenceConfigurer dbType)
{
var cfg = dbType.ConfigureProperties(new Configuration());
new AutoPersistenceModel()
.Conventions.Add()
.Where(x => x.Namespace.EndsWith("Domain"))
.Conventions.Add<MyStringLengthConvention>()
.AddEntityAssembly(typeof(NHSample2.Domain.News).Assembly)
.Configure(cfg);
return cfg;
}
نکته:
اگر برای یافتن اطلاعات بیشتر در این مورد در وب جستجو کنید، اکثر مثالهایی را که مشاهده خواهید کرد بر اساس نگارش بتای fluent NHibernate هستند و هیچکدام با نگارش نهایی این فریم ورک کار نمیکنند. در نگارش رسمی نهایی ارائه شده، تغییرات بسیاری صورت گرفته که آنها را در این آدرس میتوان مشاهده کرد.
دریافت سورس برنامه قسمت ششم
ادامه دارد ...