ورود

View Full Version : سوال: خطا در ارتباط یک به چند و کلید خارجی Code First



oracle_dba
جمعه 09 بهمن 1394, 17:46 عصر
سلام
من از Code First استفاده می کنم ولی زمان Update بانک اطلاعاتی از کلید خارجی بین دو جدول استان و شهر ایراد میگیره . نت رو زیر و رو کردم ولی نتیجه ای نگرفتم .
با این روشی که رفتم مشکل از کجاست
کلاس شهر
138728
کلاس استان
138729
کلاس کشور
138730
خطا و دستوری که برای Update بانک زدم
138731

ممنون میشم راهنمایی کنید .

salar IT man
جمعه 09 بهمن 1394, 18:03 عصر
شما لطفا کد های مربوط به کلاس ها قرار دهید. با توجه به تصاویر مشکلی وجود ندارد که باعث این خطا شود.
چون حالتی وجود ندارد تا رکورد های شهر ها به دو طریق حذف شوند

salar IT man
جمعه 09 بهمن 1394, 18:16 عصر
شاید بهتر باشد دیتابیس را حذف کرده (اگر موجود است) ؛ بعد فایل مربوط به ورژن mirgration را که احتمالا ساخته اید را هم حذف کنید. سپس با دستور Add-Migration Initial تمام تنظیمات ردیابی شده و بعد دوباره Update-database رو اعمال کنید.

oracle_dba
شنبه 10 بهمن 1394, 16:26 عصر
همین کار رو انجام میدم ولی بازم همین خطا رو میده . متوجه منظورتون نشدم کد های چی رو بذارم ؟؟؟؟

salar IT man
شنبه 10 بهمن 1394, 20:49 عصر
همین کار رو انجام میدم ولی بازم همین خطا رو میده . متوجه منظورتون نشدم کد های چی رو بذارم ؟؟؟؟
عرض کردم کدی که در تصویر مشخصه ، مشکلی ندارد (اگر تمام خصوصیات اینهایی باشد که در تصویر مشخص است). شما از code-base migration استفاده میکنید ، کلاسی که با دستور اگر بعد از ایجاد کلاس migration مورد نظر با دستور add-migration ، تغییراتی جدید در مدل داده اید ، لازم است دوباره یک بار دیگر ورژن جدیدی از کلاس مذکور را با تغییرات جدید ایجاد کنید به صورت زیر
add-migration AddSomeProperty
و بعد هم دوباره تغییرات را اعمال کنید : update-database.

کدهای مدل هایتان را به همراه کلاس ساخته شده با دستور add-migration را قرار دهید اینجا .

oracle_dba
شنبه 10 بهمن 1394, 21:00 عصر
سلام و ممنون آقای سالار
با حذف کلمه Virtual از سمت ارتباط یک مشکل رفع شد . نفهمیدم چرا ولی مشکل حل شد . یه فیلد اضافی غیر از اون چیزی که من به عنوان کلید خارجی در نظر گرفتم می سازه که Allow Null هم هست و هیچ مقداری هم توش ذخیره نمیشه

hakim22
یک شنبه 11 بهمن 1394, 17:01 عصر
مشکل در تنظیم Cascade هست. یعنی وقتی یک کلید خارجی حذف میشه تمام رکوردهایی که به اون کلید رفرنس دادن هم حذف میشن. به این حالت Cascade میگن. (همین حالت موقع تغییر آی دی کلید خارجی هم هست) شما باید در ModelBuider در کلاس DbContext فیلد مورد نظر رو از حالت Cascadeبردارید. از WillCascadeOnDelete(false) استفاده کنید.

(ظاهرا در مدل شما Casecade حالت Cycle داره. به این معنی که وقتی با حذف یک کلید خارجی باید یک ردیف از یک جدول دیگه حذف بشه خودش منجر به حذف ردیف یا یک کلید خارجی میشه که به کلید اولیه وصله !) مثل ماری که میخواد دمه خودشو بخوره !

r4hgozar
یک شنبه 11 بهمن 1394, 18:09 عصر
سلام.
خوب دوستان نظر دادن.
اما من کد بالا رو که می بینم اشتباس.
شما foriegn key رو اصلا نیاز ندارین بزارد. البته گذاشتنش مشکلی نیست اما در ارتباط یک به چند اصلا ضرورتی به گذاشتن اون نیست.
دوما اینکه شما foriegnkey رو قرار دادی حتما باید بری و در modelBuilder تنظیم کنی.
حالا می تونی این تنظیمات در یک کلاس invertall در خود کلاس مقصدت باشه و فقط در DBCOntext شما configuration بشه و یا کلا در همون modelbuider باشه.

ولی کلا به نظرم از foriegn استفاده نکنی بهتره.
موفق باشی

r4hgozar
یک شنبه 11 بهمن 1394, 18:10 عصر
راستی نباید vitrual رو هم حذف کنید و الی اعمال lazy loding رو باید بصورت دستی خودتون انجام بدین.
این هم منبعی که میاد و توضیح میده چیزی رو که شما انجام دادین.
http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx

salar IT man
یک شنبه 11 بهمن 1394, 18:28 عصر
سلام.
خوب دوستان نظر دادن.
اما من کد بالا رو که می بینم اشتباس.
شما foriegn key رو اصلا نیاز ندارین بزارد. البته گذاشتنش مشکلی نیست اما در ارتباط یک به چند اصلا ضرورتی به گذاشتن اون نیست.
دوما اینکه شما foriegnkey رو قرار دادی حتما باید بری و در modelBuilder تنظیم کنی.
حالا می تونی این تنظیمات در یک کلاس invertall در خود کلاس مقصدت باشه و فقط در DBCOntext شما configuration بشه و یا کلا در همون modelbuider باشه.

ولی کلا به نظرم از foriegn استفاده نکنی بهتره.
موفق باشی

استفاده از آن یک Best Practice میباشد. ایشون با استفاده از Attribute ها کلید خارجی را معرفی کردند. کدشان درست است. دقت کنید در ارتباط ها یک به چند اگر این کلید خارجی را به صراحت معرفی نکنید .. هنگام درج یک رکورد در طرف چند ، باید یک کوئری بزنید تا خود طرف یک رو واکشی کنید . مطالعه بیشتر (http://www.dotnettips.info/post/926/%DA%A9%D8%A7%D8%B1-%D8%A8%D8%A7-%DA%A9%D9%84%DB%8C%D8%AF%D9%87%D8%A7%DB%8C-%D8%A7%D8%B5%D9%84%DB%8C-%D9%88-%D8%AE%D8%A7%D8%B1%D8%AC%DB%8C-%D8%AF%D8%B1-ef-code-first)

r4hgozar
یک شنبه 11 بهمن 1394, 18:49 عصر
هنگام درج یک رکورد در طرف چند ، باید یک کوئری بزنید تا خود طرف یک رو واکشی کنید . مطالعه بیشتر (http://www.dotnettips.info/post/926/%DA%A9%D8%A7%D8%B1-%D8%A8%D8%A7-%DA%A9%D9%84%DB%8C%D8%AF%D9%87%D8%A7%DB%8C-%D8%A7%D8%B5%D9%84%DB%8C-%D9%88-%D8%AE%D8%A7%D8%B1%D8%AC%DB%8C-%D8%AF%D8%B1-ef-code-first)
متوجه منظورتون در این این خط متوجه نشدم. من کلا نمی تونم ارتباط خوبی با مقالات سات tips داشته باشم چون ترجمس و نمی دونم چرا نمی تونم خوب باهاش ارتباط برقرار کنم واس همین نمی خونمش متاسفانه.
من چون از اول که mvc رو شروع کردم با coefirst کار کردم چیزی که در عمل برای من انجام شده رو گفتم.
حرف شما درسته که اون یک روش بهتر هست و بخاطر همین هم من منبع رو براشون گذاشتم.

شما وقتی میای و بعد کلید خارجی که من در بالا گفتم و کلمه virtual رو استفاده می کنی خود کد فرست میاد و اون رو به عنوان کلید خارجی جدول معرفی شده در این جدول مقصد میشناسه.
من فقط بر حسب تجربه گفتم.
به نظر من استفاده از foriegn برای زمانی ضروریه که شما داری از ارتباط یک به یک و یا یک به صفر استفاده می کنید یعنی زمانی که در جدول دوم اصلا کلید وجود نداره.
البته اونجا هم می تونید از کلمه forigenkey استفاده نکنی و با fluntapi بیای و تنظیمات رو انجام بدی که حالا از مبحث این تاپیک خارجه.

من نمونه ای رو که خودم تست گرفتم از ارتباط یک به چند اینجا قرار میدم.



public class Post
{
[Key]
public int Id { get; set; }
public string PostUrl { get; set; }
public int? Tartib { get; set; }
[MaxLength(200)]
public string Title { get; set; }
public string Body { get; set; }
public string Description { get; set; }

public DateTime? IDateTime { get; set; }
public DateTime? UDatetime { get; set; }


//relation

public virtual IEnumerable<Comment> Comments { get; set; }




}



این همه کلاس کامنت




[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }

//relation
public int PostId { get; set; }
public virtual Post Post { get; set; }




این هم یک ارتباط یک به چند بدون هیچ گونه مشکلی.

salar IT man
یک شنبه 11 بهمن 1394, 20:57 عصر
متوجه منظورتون در این این خط متوجه نشدم. من کلا نمی تونم ارتباط خوبی با مقالات سات tips داشته باشم چون ترجمس و نمی دونم چرا نمی تونم خوب باهاش ارتباط برقرار کنم واس همین نمی خونمش متاسفانه.
من چون از اول که mvc رو شروع کردم با coefirst کار کردم چیزی که در عمل برای من انجام شده رو گفتم.
حرف شما درسته که اون یک روش بهتر هست و بخاطر همین هم من منبع رو براشون گذاشتم.

شما وقتی میای و بعد کلید خارجی که من در بالا گفتم و کلمه virtual رو استفاده می کنی خود کد فرست میاد و اون رو به عنوان کلید خارجی جدول معرفی شده در این جدول مقصد میشناسه.
من فقط بر حسب تجربه گفتم.
به نظر من استفاده از foriegn برای زمانی ضروریه که شما داری از ارتباط یک به یک و یا یک به صفر استفاده می کنید یعنی زمانی که در جدول دوم اصلا کلید وجود نداره.
البته اونجا هم می تونید از کلمه forigenkey استفاده نکنی و با fluntapi بیای و تنظیمات رو انجام بدی که حالا از مبحث این تاپیک خارجه.

من نمونه ای رو که خودم تست گرفتم از ارتباط یک به چند اینجا قرار میدم.



public class Post
{
[Key]
public int Id { get; set; }
public string PostUrl { get; set; }
public int? Tartib { get; set; }
[MaxLength(200)]
public string Title { get; set; }
public string Body { get; set; }
public string Description { get; set; }

public DateTime? IDateTime { get; set; }
public DateTime? UDatetime { get; set; }


//relation

public virtual IEnumerable<Comment> Comments { get; set; }




}



این همه کلاس کامنت




[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }

//relation
public int PostId { get; set; }
public virtual Post Post { get; set; }




این هم یک ارتباط یک به چند بدون هیچ گونه مشکلی.

چیزی که Best Practice هست همون مشخص کردن PostId هستش . بس نظر ارسالی قبلی خود را اصلاح کنید.


دوما اینکه شما foriegnkey رو قرار دادی حتما باید بری و در
modelBuilder تنظیم کنی.
"حتما" اشتباه است در موردی که فرمودید. Fluent API یا Attribute .
این که PostId را به عنوان کلید خارجی در نظر میگیرد به دلیل قراردادی است که EF در نظر گرفته (میشه شخصی سازی هم کرد).اگر از یک نام دیگر استفاده کنید لازم است از Fluent API یا Attribute استفا کنید.

پست شما گمراه کننده بود البته با یک اشتباه جزئی که اشاره کردم بالا.مورد بعدی ربطی بین Virtual تعریف کردن و موردی که گفتید وجود ندارد. صرفا برای lazy loading این مورد رعایت میشود.حداقل خواندن کتابهایی (http://www.ebooksworld.ir/label/index/12/entity-framework/entity-framework) که به قول شما ترجمه شده است در سایت دات نت تیپس هم میتونه مفید باشد.

r4hgozar
دوشنبه 12 بهمن 1394, 08:04 صبح
چیزی که Best Practice هست همون مشخص کردن PostId هستش . بس نظر ارسالی قبلی خود را اصلاح کنید.


دوما اینکه شما foriegnkey رو قرار دادی حتما باید بری و در

modelBuilder تنظیم کنی.

"حتما" اشتباه است در موردی که فرمودید. Fluent API یا Attribute .
این که PostId را به عنوان کلید خارجی در نظر میگیرد به دلیل قراردادی است که EF در نظر گرفته (میشه شخصی سازی هم کرد).اگر از یک نام دیگر استفاده کنید لازم است از Fluent API یا Attribute استفا کنید.

پست شما گمراه کننده بود البته با یک اشتباه جزئی که اشاره کردم بالا.مورد بعدی ربطی بین Virtual تعریف کردن و موردی که گفتید وجود ندارد. صرفا برای lazy loading این مورد رعایت میشود.حداقل خواندن کتابهایی (http://www.ebooksworld.ir/label/index/12/entity-framework/entity-framework) که به قول شما ترجمه شده است در سایت دات نت تیپس هم میتونه مفید باشد.

سلام اقای سالار.
من نیازی به ادامه دادن بحث نمی بینم.
چون شما فقط با کلمات بازی کردین و دوباره همونایی که من گفتم رو گفتین. من سعی کردم کتابیش نکنم. حالا هر چی شما می گی درست.

در مورد حداقل کتاب خواندن در سایت دات نت باید بگم که اونها کتاب نیست و مقاله هست و دوما هم این که من نگفتم بده گفتم من نمی تونم باهاش ارتباط برقرار کنم. من نیومدم اینجا سایتی رو خراب کنم و یا از سایتی دفاع کنم.
موفق باشید