PDA

View Full Version : بهترین روش برای اپدیت پایگاه داده در entity framework



pouria_bayat
پنج شنبه 15 مهر 1395, 10:19 صبح
سلام دوستان فرض کنید 30 تامشتری دارید و توی آپدیت جدید برنامتون یکسیری فیلدها به پایگاه داده اضافه می کنید یا حتی یک جدول جدید. به نظرتون بهترین روش برای اپدیت برنامه و پایگاه داده بدون اینکه اطلاعات از بین بره چی میتونه باشه.
در ضمن فرض کنید از EntityFramework استفاده می کنیم.
تشکر.

ali_md110
پنج شنبه 15 مهر 1395, 10:34 صبح
migration در ef و به روش code first اینکار به راحنی انجام میده

pouria_bayat
پنج شنبه 15 مهر 1395, 10:56 صبح
ممنون علی جان جواب نمیده برای من فقط توی ASP تونتسم درست ازش استفاده کنم البته اونم به صورت دستی نه Auto . نمیدونم. به نظرت به خاطر اینکپایگاه داده رو در جای دیگه ذخیره میکنم و به خاطر کانکشن استرینگ نیست؟!

pouria_bayat
پنج شنبه 15 مهر 1395, 11:01 صبح
یک سوال دیگه پیش میاد برام اینکه اگر از Migration استفاده کنم برای ورژن های مختلف چه تمهیدادتی داره مثلا اگر ورژن برنامه من 5 باشه و مشتری ورژن 3 رو داشته باشه و یک مشتری دیگه ورژن 4 رو خب برای هر ورژن من باید یک Migrate جدید بسازم درسته؟ و اینکه خود برنامه تشخیص میده اول کدوم Migrate رو باید اجرا کنه!؟ کمی نگرانم نشه. منظورم رو بهتر بخواهم بگم اینه که مشتری بخواهد برنامه رو یکدفعه چندین ورژن رو بروز کنه مثلا از ورژن 3 یکدفعه بخواهد بره ورژن 6

mrprestige
پنج شنبه 15 مهر 1395, 12:11 عصر
عرض سلام و ادب خدمت شما دوست عزیز ، با اجازه از دوست عزیز جناب ali_md110 (http://barnamenevis.org/member.php?18325-ali_md110) ؛



برای من فقط توی ASP تونتسم درست ازش استفاده کنم البته اونم به صورت دستی نه Auto . نمیدونم. به نظرت به خاطر اینکپایگاه داده رو در جای دیگه ذخیره میکنم و به خاطر کانکشن استرینگ نیست؟!

دوست من شما نفرمودید از چه راهی عمل Migration رو انجام دادید که نتیجه نگرفتید ، با این حال بنده از اول براتون توضیح میدم که اگه مشکل هم بود برطرف بشه . خب اول شما صفحه Package Manager Console رو باز کنید توی قسمت Power Shell ی که در پایین صفحه باز میشه این دستور رو بنویسید


enable-migrations

صبر کنید عملیات با موفقیت به اتمام برسه وقتی عملیات به اتمام رسید در پنل Explorer که مشاهده کنید مبینید که یه پوشه به نام Migration ایجاد شده که داخل یک کلاس Configuration قرارداره داخل این کلاس برید و یک سازنده ایجاد کنید و داخلش این کد رو بنویسید

AutomaticMigrationsEnabled = true;

حالا وارد کلاس Context تون بشین و این استراتژی رو برای Migrate کردن دیتابیس بنویسید

Database.SetInitializer(new MigrateDatabaseToLatestVersion<DBContext, Migrations.Configuration>());


بعد از اون توی همین کلاس متد OnModelCreating رو Override میکنیم

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

}




کلا پیاده سازی Migration به این صورت هست حالا بنده تعریف جدول و مقدار دهی ستون و ... نگفتم چون فقط خواستم شما تعریف Migration رو بدونید . البته اینم بگم میتونستید هم تمام این مراحل رو بصورت کدنویسی ( بدون استفاده از PowerShell ) انجام بدید که بنده سریعترین راه رو عرض کردم براتون .

و در خصوص جواب سوالی که در پست دومتون گذاشتید ، باید عرض کنم درست متوجه فرمایشتون نشدم وقتی شما از اون استراتژی ک در بالا عرض کردم استفاده کنید فکر نمیکنم دیگه لازم نیست نگران این باشید که چه ورژنی از برنامه استفاده میشه

اگه سوالی براتون باز پیش اومد بنده و باقی دوستان پاسخ میدیم .

پیروز و موفق باشید

pouria_bayat
پنج شنبه 15 مهر 1395, 13:17 عصر
و در خصوص جواب سوالی که در پست دومتون گذاشتید ، باید عرض کنم درست متوجه فرمایشتون نشدم وقتی شما از اون استراتژی ک در بالا عرض کردم استفاده کنید فکر نمیکنم دیگه لازم نیست نگران این باشید که چه ورژنی از برنامه استفاده میشه

اگه سوالی براتون باز پیش اومد بنده و باقی دوستان پاسخ میدیم .





ممنون بابت پاسخ زیباتون دقیقا تمام روشهای گفته شده رو قبلا پیاده سازی کردم. شاید عدم شناخت دقیق من از Migration هستش.
سوالم رو واضح تر میپرسم.
1- آیا برای هر ورژن یا تغییری من باید توی پوشه Migrations یک کلاس جدید بسازم یا به عبارتی یک کلاس جدید Migrate کنم؟ فرضا برای ورژن 5 به 5.1
2- وقتی Add-migration رو میزنم فرضا با نام upd عمل میگریت به درستی انجام میشه و پایگاه داده آپدیت میشه. یک جایی توی آموزشهای مایکروسافت دیدم بعد از اپدیت پایگاه داده برای اینکه مطمئن بشه اپدیت به درستی انجام گرفته دوباره add-migration میزد و اگر چیزی برای اپدیت نبود کلاس خالی میموند. اما اینجا اگر بخواهم اینکارو بکنم عملا تغییرات از بین میره و اگر بخواهم Add-migrate با یک نام دیگه بزنم میگه شما کلاسی قبلا ایجاد کردید که باید از همون نام ساتفاده کنید متن پیام:

Unable to generate an explicit migration because the following explicit migrations are pending: [201610060856494_upd]. Apply the pending explicit migrations before attempting to generate a new explicit migration.

3- اینکه من برای هر ورژن باید یکبار Add-migrate رو بزنم و تغییرات کلاسی که ساخته میشه(migrate) میشه رو تغییر ندم و نگه بدارم توی برنامه تا زمانی اگر کاربر خواست اپدیت انجام بده فرضا از ورژن 1 بره به ورژن 2 بتونه راحت اینکارو بکنه. اما سوال من از ورژن یک تا 5 نزدیک به 5 بار پایگاه داده رو تغییر دادم و 5 تا Migrate ساختم آیا CodeFirst میتونه تشخیص بده و کدام کلاس Migrate رو اجرا میکنه؟

بازم تشکر.

pouria_bayat
پنج شنبه 15 مهر 1395, 13:59 عصر
کد بالا میگه باید دستور Update-Database اجرا بشه تا بتونیم یک Migrate جدید بسازیم اما چطور کاربر که نمیتونه اینکارو بکنه!!!!اگر
AutomaticMigrationsEnabled = true;



اینکارو میکنه پس چرا پیغام زیر میاد؟

Unable to generate an explicit migration because the following explicit migrations are pending: [201610061046437_V4.9T5.0]. Apply the pending explicit migrations before attempting to generate a new explicit migration.

در کل آیا راهی وجود داره که بشه Migrate ورژنهای مختلف فرضا از 1 به 1.1 و از 1.1 به 1.2 و ... را ایجاد کرد؟

ali_md110
پنج شنبه 15 مهر 1395, 15:36 عصر
منظورتون از ورژن 1 تا 5 چیه؟
منظورتون ورژن برنامست یا EF
اگر منظورتون پروژه خودتونه ورژن اون ربطی به میگریشن نداره
در کل:
وقتی دستور enable-migrations رو صادر کردید یک فولدر بنام Migrations اضافه میشه به همراه یک کلاس بنام Configuration


public class Configuration : DbMigrationsConfiguration<ApplicationDbContext>
{
public Configuration()

{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;

}
protected override void Seed(ApplicationDbContext context)
{
}}

همین متد توی استارت اپ برنامه صدا بزنید


Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>());


ورژن Ef رو هم از nuget به 6 ارتقا بدید
چون میگریشن ورژن 7 کمی متفاوت شده

pouria_bayat
پنج شنبه 15 مهر 1395, 17:52 عصر
با سلام دقیقا منظورم از ورژن برنامه خودم بود.
اما مشگل کار رو پیدا کردم یک برنامه ساده نوشتم و یک کلاس Test برای جدولش تعریف کردم دفعه اول (ورژن یک) فقط یک فیلد به نام Name براش گذاشتم و پایگاه داده رو ساختم
دفعه دوم (ورژن دو)یک فیلد جدید بهش اضافه کردم با نام Family و Add-migration upd2 رو زدم و کلاس upd2 ساخته شد. در نتیجه در زمان اجرای برنامه فیلد Family به درستی به جدول اضافه شد.
دفعه سوم (ورژن سه) یک فیلد دیگه با نام FatherName به کلاس Test اضافه کردم و این دفعه Add-migration upd3 رو زدم و به درستی کلاس upd3 ساخته شد. و بعد از اجرای برنامه به درستی فیلد FatherName به پایگاه داده اضافه شد.
اما مشگل توی برنامه اصلی :
توی برنامه اصلی خودم Migration با اینکه true هستش ولی کار نمیکنه دلیلشم نمیدونم چیه فقط این رو میدونم وقتی یکبار Add-migration میزنم دفعه دوم اگر تغییری توی جدول بدم حتما نیاز هست Update-database رو بزنم در صورتی که برنامه دست مشتری است و این امکان وجود نداره به نظرتون مشگل چی میتونه باشه؟!!!!

ali_md110
پنج شنبه 15 مهر 1395, 18:53 عصر
به چه دلیل وقتی Migration بصورت اتوماتیک میشه انجام داد شما Add-Migration رو صذا میزنید؟

dbo.__MigrationHistory جدولی برای ذخیره سوابق تغییرات Migration هست و نیازی به ساخت فایلهای cs ندارید

pouria_bayat
پنج شنبه 15 مهر 1395, 19:38 عصر
این موضوع رو نمیدونستم که بدون نیاز به Add-Migration کردن میشه پایگاه داده رو اپدیت کرد.
تشکر.
بازم خطا بدون add-migrate :
there is already an object name "TableName" in the database
جالبه وقتی Add-migration میزنم توی کلاس ساخته شده تمامی جداول را Drop میکنه و شروع میکنه تمامی فیلدها رو اپدیت کردن!!!!

ali_md110
پنج شنبه 15 مهر 1395, 21:40 عصر
خطای شما به چند دلیل است اگر AutomaticMigrationsEnabled به true تنظیم کردید در زمان Add-migration به حالت false دربیارید
دوم ممکنه اینکه از روی دیتابیس موجود مهندسی معکوس کردید و جدولdbo.__MigrationHistory وجود ندارد یا اگر هم هست ناقص است و باید دستور add-migration Initial -IgnoreChanges
صادر و سپس دستور
update-database
برای به روزرسانی جدول dbo.__MigrationHistory

pouria_bayat
پنج شنبه 15 مهر 1395, 23:20 عصر
مشگل رو پیدا کردم مشگل من در مسر اجرای برنامه یک پوشه درست کردم به نام دیتابیس و توی اون دیابیس رو قرار می دادم :

public DBServerContext()
: base("name=" + DBName)
{
var appDataDir = Application.StartupPath + @"\Database\";
//var appDataDir = @"C:\Database\";
AppDomain.CurrentDomain.SetData("DataDirectory", appDataDir);

}


کانکشن استرینگ من به شکل زیر بود:

<connectionStrings>
<add name="DBServerContext" connectionString="data source=.\SqlExpress;AttachDBFilename=|DataDirector y|\DBServerContext.mdf;Initial Catalog=DBServerContext.mdf;integrated security=True;MultipleActiveResultSets=True;App=En tityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>



حالا وقتی کDataDirectory رو بر میدارم Migration درست جواب میده. وقتی میزارم همون مشگلات قبل وجود داره. آیا راهی وجود داره Migration درست جواب بده ولی پایگاه داده رو توی پوشه دلخواه جای دیگه ذخیره کنم؟ تشکر

mrprestige
جمعه 16 مهر 1395, 11:39 صبح
مجددا سلام دوست من ، بله میتونید ولی به نظر این حقیر اصلا این کار اصولی نیست و بهتره پایگاهتون داخل مسیر پروژه تون باشه تا در واقع به زبان ساده تر هنگام نهایی کردن برنامه به مشکل برنخورید

ali_md110
جمعه 16 مهر 1395, 12:17 عصر
مشگل رو پیدا کردم مشگل من در مسر اجرای برنامه یک پوشه درست کردم به نام دیتابیس و توی اون دیابیس رو قرار می دادم :

public DBServerContext()
: base("name=" + DBName)
{
var appDataDir = Application.StartupPath + @"\Database\";
//var appDataDir = @"C:\Database\";
AppDomain.CurrentDomain.SetData("DataDirectory", appDataDir);

}


کانکشن استرینگ من به شکل زیر بود:

<connectionStrings>
<add name="DBServerContext" connectionString="data source=.\SqlExpress;AttachDBFilename=|DataDirector y|\DBServerContext.mdf;Initial Catalog=DBServerContext.mdf;integrated security=True;MultipleActiveResultSets=True;App=En tityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>



حالا وقتی کDataDirectory رو بر میدارم Migration درست جواب میده. وقتی میزارم همون مشگلات قبل وجود داره. آیا راهی وجود داره Migration درست جواب بده ولی پایگاه داده رو توی پوشه دلخواه جای دیگه ذخیره کنم؟ تشکر
مسیر دیتابیس در رشته اتصال هیچ ربطی به Migration نداره
مشکل کار شما ممکنه جای دیگه باشه
شما میتونید دیتابیستون توی فولدرهای تو در تو بزارید
کلا Migration تو بعضی پروژه ها کمی گیر میده که ممکنه مشکل از ها Temp یا فایلهای مزاحم دیگه باشه