PDA

View Full Version : سوال: آپدیت یا ساخت مجدد مدل در زمان اجرا در EF



spring69
شنبه 10 تیر 1391, 22:52 عصر
من میخوام مدلم رو در زمان اجرا دوباره سازی کنم. یعنی در صورتی که کاربر هر تغییری در ساختار بانک داد، روی مدلم اعمال بشه.
آیا روشی هست برای این کار در Entity Framework؟
---
در واقع میخوام مدل بانکم رو در زمان اجرا بسازم.

reza1984
شنبه 10 تیر 1391, 23:45 عصر
با اولين بار اجراي برنامه، يك بانك اطلاعاتي پيش فرض نيز توليد خواهد شد. يا اگر تعاريف ويژگي‌هاي يك فيلد را تغيير داديم، نياز است تا بانك اطلاعاتي را دستي drop كرده و اجازه دهيم تا بانك اطلاعاتي جديدي بر اساس تعاريف جديد مدل‌ها تشكيل شود كه ... هيچكدام از اين‌ها بهينه نيستند.
در اينجا دو استراتژي مقدماتي را در حين آغاز يك برنامه مي‌توان تعريف كرد:

view plaincopy to clipboardprint?
System.Data.Entity.Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context>());
// or
System.Data.Entity.Database.SetInitializer(new DropCreateDatabaseAlways<Context>());

مي‌توان بانك اطلاعاتي را در صورت تغيير اطلاعات يك مدل به صورت خودكار drop كرده و نسبت به ايجاد نمونه‌اي جديد اقدام كرد (DropCreateDatabaseIfModelChanges)؛ يا در حين آزمايش برنامه هميشه (DropCreateDatabaseAlways) با شروع برنامه، ابتدا بايد بانك اطلاعاتي drop شده و سپس نمونه جديدي توليد گردد.
محل فراخواني اين دستور هم بايد در نقطه آغازين برنامه، پيش از وهله سازي اولين DbContext باشد. مثلا در برنامه‌هاي وب در متد Application_Start فايل global.asax.cs يا در برنامه‌هاي WPF در متد سازنده كلاس App مي‌توان بانك اطلاعاتي را آغاز نمود.
البته الزامي به استفاده از كلاس‌هاي DropCreateDatabaseIfModelChanges يا DropCreateDatabaseAlways وجود ندارد. مي‌توان با پياده سازي اينترفيس IDatabaseInitializer از نوع كلاس Context تعريف شده در برنامه، همان عمليات را شبيه سازي كرد يا سفارشي نمود:

view plaincopy to clipboardprint?
public class MyInitializer : IDatabaseInitializer<Context>
{
public void InitializeDatabase(Context context)
{
if (context.Database.Exists() ||
context.Database.CompatibleWithModel(throwIfNoMeta data: false))
context.Database.Delete();

context.Database.Create();
}
}


public class MyInitializer : IDatabaseInitializer<Context>
{
public void InitializeDatabase(Context context)
{
if (context.Database.Exists() ||
context.Database.CompatibleWithModel(throwIfNoMeta data: false))
context.Database.Delete();

context.Database.Create();
}
}

سپس براي استفاده از اين كلاس در ابتداي برنامه، خواهيم داشت:


view plaincopy to clipboardprint?
System.Data.Entity.Database.SetInitializer(new MyInitializer());

System.Data.Entity.Database.SetInitializer(new MyInitializer());


نكته:
اگر از يك بانك اطلاعاتي موجود استفاده مي‌كنيد (محيط كاري) و نيازي به پيش فرض‌هاي EF Code first نداريد و همچنين اين بانك اطلاعاتي نيز نبايد drop شود يا تغيير كند، مي‌توانيد تمام اين پيش فرض‌ها را با دستور زير غيرفعال كنيد:


view plaincopy to clipboardprint?
Database.SetInitializer<Context>(null);

Database.SetInitializer<Context>(null);

بديهي است اين دستور نيز بايد پيش از ايجاد اولين وهله از شيء DbContext فراخواني شود.


همچنين بايد درنظر داشت كه در آخرين نگارش‌هاي پايدار EF Code first، اين موارد بهبود يافته‌اند و مبحثي تحت عنوان DB Migration ايجاد شده است تا نيازي نباشد هربار بانك اطلاعاتي drop شود و تمام اطلاعات از دست برود. مي‌توان صرفا تغييرات كلاس‌ها را به بانك اطلاعاتي اعمال كرد كه به صورت جداگانه، در قسمتي مجزا بررسي خواهد شد. به اين ترتيب ديگر نيازي به drop بانك اطلاعاتي نخواهد بود. به صورت پيش فرض در صورت از دست رفتن اطلاعات يك استثناء را سبب خواهد شد (كه توسط برنامه نويس قابل تنظيم است) و در حالت خودكار يا دستي با تنظيمات ويژه قابل اعمال است.

spring69
یک شنبه 11 تیر 1391, 08:39 صبح
خیلی ممنون از جوابتون
فکر این حالت هایی که گفتین همه برای زمانی هست که مدل تغییر کنه و ما بخوایم بانکمون رو طبق مدل بروزرسانی کنیم ( در کد نویسی کد فرست)
حالا من حالتی عکس این حالت رو میخوام. یعنی چطور زمانی که من برنامه رو رلیز کردم و دادم دست مشتری، و مشتری به دلایلی (بانک مال اونهاست)، اون رو تغییر، مدلم هم که الان از روی بانک ساختم بروزرسانی بشه.
من کدهام همه با رفلکشن نوشته شده و هیچ محدودیتی از نظر ایجاد خطا در برنامه در صورت تغییر بانک ندارم. اما، اگر مدل من طبق بانک بروز نباشه عملا هیچ کاربردی نخواهد داشت
ممنون میشم برای این حالت هم نظرتون رو بگید

reza1984
یک شنبه 11 تیر 1391, 17:23 عصر
Nuget EntityFramework یه ابزاری داره که شما میتونین از بانکی که دارین کلاس ایجاد کنین
خیلی سادس