asp.net mvc - EF Code First - Populating data in Many to Many -
i'm new asp.net mvc , want create simple blog project, therefore have 2 entity posts
, categories
. each post can belong many categories , each category can belong many posts.
models.cs
public class category { [key] public int categoryid { get; set; } public int? parentid { get; set; } public virtual category parent { get; set; } public string title { get; set; } public string description { get; set; } public virtual icollection<news> news { get; set; } public category() { news = new list<news>(); } } public class news { [key] public int newsid { get; set; } public string title { get; set; } public string summary { get; set; } public string content { get; set; } public string source { get; set; } public string sourceurl { get; set; } public string images { get; set; } public string password { get; set; } public datetime createdat { get; set; } public datetime? modifiedat { get; set; } public datetime? deletedat { get; set; } public string createdby { get; set; } public string deletedby { get; set; } public virtual publishperiod publishperiodid { get; set; } public virtual icollection<category> categories { get; set; } public news() { categories = new list<category>(); }
}
modelsmap.cs
public class categorymap:entitytypeconfiguration<category> { public categorymap() { property(one => one.title).hasmaxlength(100).isrequired(); hasoptional(x => x.parent).withmany().hasforeignkey(x => x.parentid); } } public class newsmap:entitytypeconfiguration<news> { public newsmap() { property(x => x.createdby).hasmaxlength(150); property(x => x.deletedby).hasmaxlength(150); property(x => x.title).isrequired().hasmaxlength(150); property(x => x.summary).isrequired(); property(x => x.content).isrequired().hascolumntype("ntext"); property(x => x.createdat).hascolumntype("datetime"); property(x => x.password).isoptional().hasmaxlength(128); property(x => x.deletedat).isoptional(); property(x => x.modifiedat).isoptional(); hasmany(x => x.categories).withmany(x => x.news).map(x => { x.totable("newscategories"); x.mapleftkey("news_newsid"); x.maprightkey("category_categoryid"); }); } }
and db context
public dbset<category> categories { get; set; } public dbset<news> news { get; set; } public dbset<publishperiod> publishperiod { get; set; } protected override void onmodelcreating(dbmodelbuilder modelbuilder) { base.onmodelcreating(modelbuilder); modelbuilder.configurations.add(new categorymap()); modelbuilder.configurations.add(new newsmap()); modelbuilder.configurations.add(new publishperiodmap());
i have create view posts
displays categories in list checkboxs , each checkbox value category's id. how can insert or update posts , keep relation between post , categories.
newscontroller
// // post: /admin/news/create [httppost] public actionresult create(news news, list<string> category) { viewbag.categories = catrepository.all.orderby(x => x.title); if (modelstate.isvalid) { foreach (var item in category) { news.addcategory(catrepository.find(int.parse(item))); } news.createdat = datetime.now; news.createdby = "m.hesabi"; newsrepository.insertorupdate(news); newsrepository.save(); return redirecttoaction("index"); } else { return view(); } }
update: created method in news
model @dans said , edited controller.
i'd recommend creating method on news class:
public void addcategory(category category) { categories.add(category); category.news.add(this); }
from controller can add each selected category news instance, , add news dbcontext prior calling savechanges. may depend, however, on how repositories make use of context -- in if open own, instead of accessing shared context, might have attach categories news repository's context prior saving. helps...
update
ientitychangetracker error:
it appears if mvcscaffolding uses separate context each repository. mentioned, having separate contexts can lead additional required steps. stands now, categories tracked context while news tracked context b-- detach/attach category entities between 2 contexts, i'd recommended solution change repositories accept shared context through constructors.
i'm assuming instantiating repositories in controller's constructor, rather using dependency injection, modify constructor code following:
mycontext = new yourcontextclass(); catrepository = new categoryrepository(mycontext); newsrepository = new newsrepository(mycontext);
you have add constructors repositories assign internal context property, , finally, adjust controller dispose of context.
protected override void dispose(bool disposing) { if (disposing) mycontext.dispose(); base.dispose(disposing); }
Comments
Post a Comment