آموزش Code First Data Annotations - بخش دوم
بسم الله الرحمن الرحیم
بخش دوم
ComplexType
نوع های پیچیده
ممکن است شما یک نوع غیر معمول برای فیلد های خود بخواهید تعریف کنید، این نوع شما ممکن است یک کلاس باشد، مثلا کلاس زیر را در نظر بگیرید:
public class BlogDetails
{
public DateTime? DateCreated { get; set; }
[MaxLength(250)]
public string Description { get; set; }
}
بسم الله الرحمن الرحیم
بخش دوم
ComplexType
نوع های پیچیده
ممکن است شما یک نوع غیر معمول برای فیلد های خود بخواهید تعریف کنید، این نوع شما ممکن است یک کلاس باشد، مثلا کلاس زیر را در نظر بگیرید:
public class BlogDetails
{
public DateTime? DateCreated { get; set; }
[MaxLength(250)]
public string Description { get; set; }
}
اگر در این کلاس که نوشته ایم دقت کنید هیچ کلید اصلی مشاهده نمی کنید. در domain driven design، کلاس BlogDetails مانند مقدار شی ارجاع داده شده است. Entity Framework مقدار اشیا را به عنوان نوع های پیچیده (Complex types) ارجاع می دهد. نوع های پیچیده نمی توانند به وسیله خودشان دنبال شوند بلکه باید به وسیله کلاس های دیگر مدیریت شوند:
در اجرا کلاس BlogDetails بخش از شی کلاس Blog خواهد شد. شما باید کلاس BlogDetails را به عنوان یک نوع پیچیده علامت گذاری کنید.
[ComplexType]
public class BlogDetails
{
public DateTime? DateCreated { get; set; }
[MaxLength(250)]
public string Description { get; set; }
}
حال پراپرتی زیر را به کلاس Blog اضافه کنید:
public BlogDetails BlogDetail { get; set; }
حال در دیتابیس پراپرتی های کلاس BlogDetail به جدول Blog اضافه می شود، تمامی پراپرتی های BlogDetail که به جدول Blog اضافه شده اند قبل از نام خود کلمه BlogDetail را دارند:
DateTime ها در دیتابیس به صورت پیش فرض nullable هستند برای اینکه آنها را به فیلدهای اجباری تغییر دهید باید از Required annotation استفاده کنید تا در schema دیتابیس شما نیز اجباری شود.
ConcurrencyCheck
بررسی همزمانی
ConcurrencyCheck annotation به شما اجازه می دهد یک یا چند پراپرتی خود در زمانی که یک کاربر یک entity را در دیتابیس حذف و ویرایش می کند، علامت گذاری کنید. برای اضافه کردن این خاصیت به صورت زیر عمل کنید.
اگر شما از EF Designer استفاده می کنید، باید ConcurrencyMode با Fixed تنظیم کنید.
با یک مثال نحوه کارکردن ConcurrencyCheck را بر روی پراپرتیBloggerName بررسی می کنیم.
[ConcurrencyCheck, MaxLength(10, ErrorMessage="BloggerName must be 10 characters or less"),MinLength(5)]
public string BloggerName { get; set; }
هنگامی که SaveChanges فراخوانی می شود، چون ConcurrencyCheck annotation بر روی فیلد BloggerName قرار گرفته، مقدار اصلی این پراپرتی در update استفاده خواهد شد. دستور تلاش می کند مقدار صحیح را با فیلتر کردن برای سطر شما قرار دهد، اما این فیلتر کردن مثل گذشته دیگر فقط بر اساس کلید اصلی نیست بلکه مقدار اصلی BloggerName که قبلا شما آن را واکشی کرده بودید که تغییر بدهید نیز در فیلتر تاثیر گذار خواهد بود.
در اینجا بخش حساس دستور Update که به دیتابیس ارسال شده است را نوشته ایم، در اینجا شما می توانید ببینید دستور سطری را update خواهد کرد که PrimaryTrackingKey آن 1 و BloggerName آن “Julie” است این ها مقادیری هستن که شما قبل از بروز رسانی دیده بودید، پس ما باید فقط سطری را بروز رسانی که کنیم که شما قبلا بر روی آن کار کردید:
where (([PrimaryTrackingKey] = @4) and ([BloggerName] = @5))
@4=1,@5=N'Julie'
اگر هر فرد دیگری در این زمان بخواهد مقدار bloggerName برای همان سطری که شما در حال بروز رسانی آن هستید، تغییر دهد، دستور update متوقف (fail) خواهد شد و شما یک خطا از نوع DbUpdateConcurrencyException دریافت خواهید کرد، که باید این خطا را برای کامل شدن کارتان مدیریت کنید.
TimeStamp
برای شماره سطرها (rowversion) یا فیلدهای timestamp در خصوص همزمانی خیلی مرسوم است. قبلا در خصوص همزمانی SQL server مطلبی را ارائه شده است، برای آشنایی بیشتر به آن مراجعه کنید.
به جای استفاده از ConcurrencyCheck annotation می توانید ازTimeStamp annotation استفاده کنید که نوع پراپرتی آن ارایه ای از بایت است. Code first با پراپرتی های Timestamp شبیه پراپرتی های ConcurrencyCheck رفتار می کند، اما اطمینان حاصل می کند که فیلد دیتابیسی که توسط Code First ایجاد شده است non-nullable باشد. شما می توانید فقط یک پراپرتی timestamp در هر کلاس داشته باشید. اگر در فکر این هستید که شما نیاز به دو timestamp دارید و الان باید چه کاری را انجام دهید تا مشکتان برطرف شود! Timestamp را متوجه نشدید، ساده توضیح می دهم، هر بار که یک رکورد بروزرسانی شود مقدار timestamp تغییر خواهد کرد و شما با یک سری از دستورا می توانید این دنباله تغییرات پیگیری کنید.
مطلبی که در خصوص timestamp در بخش SQL Server نوشته شده است حتما مطالعه کنید.
پراپرتی زیر را به کلاس Blog اضافه کنید:
[Timestamp]
public Byte[] TimeStamp { get; set; }
یک non-nullable timestamp در جدول پایگاه داده شما ایجاد خواهد شد.