Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

Witam serdecznie,
Mam problem ze stworzeniem relacji wiele do wielu w MVC 3. Relacja jeden do wielu generuje się bez problemu.
Mam takie dwie klasy:


public class Post
{
public int PostId { get; set; }
public string PostTitle { get; set; }
public string PostContent { get; set; }
public virtual ICollection<Category> Categories {get; set;}
}


i klase:


public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public virtual ICollection<Post> Posts { get; set; }

}


Mam też klasę BlogContext


public class BlogContext : DbContext
{
public DbSet<Post> Posts { get; set; }
public DbSet<Category> Categories { get; set; }
}


Korzystam z automatycznej funkcji generacji kodu. (Add Controller, Model Class, Data Context Class). Jednakże niestety nie generuja mi się pola dla Kategorii w widokach.

Będe wdzięczny za pomoc:)
P.S Korzystam z Microsoft Visual Web Developer 2010 ExpressMarcin Cembrzynski edytował(a) ten post dnia 27.06.11 o godzinie 22:14

konto usunięte

Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

A przypadkiem relacji wiele do wielu nie realizuje się poprzez 2 relacje 1 do wielu ?
Tomasz M.

Tomasz M. never go full
retard!

Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

Sebastian O.:
A przypadkiem relacji wiele do wielu nie realizuje się poprzez 2 relacje 1 do wielu ?

Dokładnie, stwórz sobie klasę PostCategory or somethin'.

Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

Witam serdecznie,
Dziękuję bardzo za pomoc

Czyli nowa klasa powinna wygladać tak:


public class PostCategory
{
public int PostId { get; set; }
public int CategoryId { get; set; }
}


a BlogContext powinien wyglądać tak:?


public class BlogContext : DbContext
{

public DbSet<Post> Posts { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<PostCategory> PostsCategories { get; set; }
}


Będę wdzięczny za pomoc:)

konto usunięte

Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

Nie do końca tak to powinno wyglądać ....
Może najpierw napisz co chcesz osiągnąć.
Z tego co piszesz to:
1. Do 1 kategorii może należeć kilka postów. [OK]
2. Jeden post może należeć do kilku kategorii ????

Według mnie dodajesz kategorię, dodajesz post do kategorii i tyle :)

Polecam do poduszki http://mvcmusicstore.codeplex.com/releases/view/64379
Ja przerobiłem to 2 razy, żeby lepiej zrozumieć :)

konto usunięte

Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

Marcin Cembrzynski:

Cześć Marcin,

Rozwiązanie z Twojego pierwszego posta powinno działać. Trzeba zdefiniować wirtualne kolekcje w obiektach oraz DbSety w context i na koniec wywołać Database.SetInitliazier(). Żeby Schema została wygenerowana na nowo musisz stworzyć obiekt BlogContext ale zakładam, że robisz to przy GET/POST request.

Do Twojego kodu z pierwszego posta dodałem tylko wywołanie Database.SetInitializer(new MyDatabaseInitializer()). W rezultacie mam w bazie tabele Posts <- CategoryPosts -> Categories



public class MvcApplication : System.Web.HttpApplication
{

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);

Database.SetInitializer(new MyDatabaseInitializer());
}
}

public class MyDatabaseInitializer : DropCreateDatabaseAlways<BlogContext>
{
}

Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

Cześć Jarosław,
Dziękuję bardzo za pomoc. Troche chyba mi sie rozjaśnia:)

Czyli nie potrzebuje klasy pośredniczacej PostCategory?
A klasa DbContext powinna wygladac tak?:


public class BlogContext : DbContext
{

public DbSet<Post> Posts { get; set; }
public DbSet<Category> Categories { get; set; }
}


Tworzac sobie widok dla Create Post musze dodatkowo stworzyc sobie
liste wielokrotnego wyboru lub też checkboxy i w kontrolerze dla Post zostanie to zapisane przez EntityFramework?


public ActionResult Create(Post post)
{


if (ModelState.IsValid)
{
db.Posts.Add(post);
db.SaveChanges();
return RedirectToAction("Index");
}

return View(post);
}


Tworzac sobie controllery i widoki korzystałem ze scaffoldingu, rozumiem, że nie dziala ona w opcji wiele do wielu.

P.S.
Zauwazylem na Twoim blogu projekt: http://code.google.com/p/rankingsejmowy/
Bede korzystał, dzieki

Jarosław D.:
Marcin Cembrzynski:

Cześć Marcin,

Rozwiązanie z Twojego pierwszego posta powinno działać. Trzeba zdefiniować wirtualne kolekcje w obiektach oraz DbSety w context i na koniec wywołać Database.SetInitliazier(). Żeby Schema została wygenerowana na nowo musisz stworzyć obiekt BlogContext ale zakładam, że robisz to przy GET/POST request.

Do Twojego kodu z pierwszego posta dodałem tylko wywołanie Database.SetInitializer(new MyDatabaseInitializer()). W rezultacie mam w bazie tabele Posts <- CategoryPosts -> Categories



public class MvcApplication : System.Web.HttpApplication
{

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);

Database.SetInitializer(new MyDatabaseInitializer());
}
}

public class MyDatabaseInitializer : DropCreateDatabaseAlways<BlogContext>
{
}

Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

Witam,
Chodzi mi o taka sytuacje kiedy jeden post należy do kilku kategorii,
(Na przykład tak jak to jest w Wordpressie)

MCV MusicStore jest super tutorialem i też z niego korzystam:)
Pozdrawiam
Sebastian O.:
Nie do końca tak to powinno wyglądać ....
Może najpierw napisz co chcesz osiągnąć.
Z tego co piszesz to:
1. Do 1 kategorii może należeć kilka postów. [OK]
2. Jeden post może należeć do kilku kategorii ????

Według mnie dodajesz kategorię, dodajesz post do kategorii i tyle :)

Polecam do poduszki http://mvcmusicstore.codeplex.com/releases/view/64379
Ja przerobiłem to 2 razy, żeby lepiej zrozumieć :)

konto usunięte

Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

Nie wiem jak to dla Jarosława zadziałało, ale u mnie nie poszło.
Działa taka wersja:

public class Post
{
public int PostId { get; set; }
public int CategoryId { get; set; }
public string Title { get; set; }
public virtual List<Category> Categories { get; set; }
}
public class Category
{
public int CategoryId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Blog: DbContext
{
public DbSet<Post> Posts { get; set; }
public DbSet<Category> Categories { get; set; }
}

Przeglądanie postów w kategoriach:

public ActionResult Index()
{
var categories = db.Categories.ToList();
return View(categories);
}

public ActionResult Browse(string category)
{
var CategoryModel = db.Categories.Include("Posts")
.Single(g => g.Name == category);
return View(CategoryModel);
}

konto usunięte

Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

Sebastian O.:
Nie wiem jak to dla Jarosława zadziałało, ale u mnie nie poszło.
Działa taka wersja:

public class Post
{
public int PostId { get; set; }
public int CategoryId { get; set; }
public string Title { get; set; }
public virtual List<Category> Categories { get; set; }
}
public class Category
{
public int CategoryId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Blog: DbContext
{
public DbSet<Post> Posts { get; set; }
public DbSet<Category> Categories { get; set; }
}

Przeglądanie postów w kategoriach:

public ActionResult Index()
{
var categories = db.Categories.ToList();
return View(categories);
}

public ActionResult Browse(string category)
{
var CategoryModel = db.Categories.Include("Posts")
.Single(g => g.Name == category);
return View(CategoryModel);
}


Oczywiście nie jestem jakimś wielkim znawcą tematu, dlatego pewnie nie jest to najlepsze rozwiązanie, ale działa :)

Edit: sorki, kliknąłem cytuj zamiast edytuj ;/

Jeszcze w Global.asax w Application_Start():

System.Data.Entity.Database.SetInitializer(new blog3.Models.SampleData());

oraz

public class SampleData: DropCreateDatabaseAlways<Blog>
{
protected override void Seed(Blog context)
{
var categories = new List<Category>
{
new Category { Name = "Rock" }
};
new List<Post>
{
new Post{ Title="It's Work !", Categories = categories.Where(g => g.Name != null).ToList()}
}.ForEach(a => context.Posts.Add(a));
}
}
Sebastian O. edytował(a) ten post dnia 30.06.11 o godzinie 14:01

konto usunięte

Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

Marcin Cembrzynski:

Tworzac sobie widok dla Create Post musze dodatkowo stworzyc sobie liste wielokrotnego wyboru lub też checkboxy i w kontrolerze dla Post zostanie to zapisane przez EntityFramework?

Marcin nie do końca rozumiem co chcesz zrobić.

@Sebastian nic nie poradzę, że u mnie to działa :)

konto usunięte

Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

Marcin zapewne pyta w jaki sposób dodając post, wybrać kategorie do których ma on należeć.Sebastian O. edytował(a) ten post dnia 30.06.11 o godzinie 21:38

Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

Witam i dziękuje

@Jarosław

Chcę stworzyć posta, który należy do wielu kategorii.

Mam taki widok:

Obrazek


Lista wielokrotnego wyboru generuje kodem:


@Html.ListBox("CategoryId", new MultiSelectList(ViewBag.Categories as System.Collections.IEnumerable, "CategoryID", "CategoryName"))


A w kontrolerze dla metody Create mam taki kod:


[HttpPost]
public ActionResult Create(Post post)
{


if (ModelState.IsValid)
{
db.Posts.Add(post);
db.SaveChanges();
return RedirectToAction("Index");
}

return View(post);
}



Ale raczej te kategorie się nie zapisuja:(

Jarosław D.:
Marcin Cembrzynski:

Tworzac sobie widok dla Create Post musze dodatkowo stworzyc sobie liste wielokrotnego wyboru lub też checkboxy i w kontrolerze dla Post zostanie to zapisane przez EntityFramework?

Marcin nie do końca rozumiem co chcesz zrobić.

@Sebastian nic nie poradzę, że u mnie to działa :)

konto usunięte

Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

W przypływie wolnego czasu zająłem się problemem i mam rozwiązanie.

@Marcin
Faktycznie Twoje rozwiązanie działa (tworzy się tabela CategoryPosts), jednak nie rozwiązuje to problemu.

Zaznaczam, że w swoich stwierdzeniach mogę się mylić, więc jakby co to poprawcie :)

No to jedziemy..

1. Jak @Html.ListBox przekazuje dane do modelu ?
Musimy mieć w modelu tablicę na zaznaczone wartości np. int[] SelectedCategories.
Czyli ogólna postać: @Html.ListBox("SelectedCategories", ...)

... są dlatego, że postanowiłem też zmienić sposób dodania kategorii do ListBoxa. Może zostać ViewBag.

2. Stworzenie modelu pomocniczego - tak to sobie nazwałem hehe

public Cpost()
{
p = new Post();
CategoriesList = GetCategories(null);
}
public Post p { get; private set; }
public MultiSelectList CategoriesList { get; private set; }
public int[] SelectedCategories { get; set; }
public MultiSelectList GetCategories(int[] selectedValues)
{
var a = new BlogContext();
List<Category> categories = a.Categories.ToList();
return new MultiSelectList(categories, "CategoryId", "CategoryName", selectedValues);
}

Służy on m.in. do: dodania kategorii do ListBoxa oraz zawiera posta i listę zaznaczonych Id.
Wiele wyjaśniania nie ma.

W kontrolerze robimy

public ActionResult Index()
{
Cpost c = new Cpost();
return View(c);
}

I już mamy Listę z kategoriami.
Tyle odnośnie modelu.
Model sam z siebie nie doda Posta z przypisanymi kategoriami do bazy, więc lecimy z kontrolerem:

[HttpPost]
public ActionResult Index(Cpost C)
{
if (C.SelectedCategories != null)
{
List<Category> categories = new List<Category>();

foreach (var selectedCat in C.SelectedCategories)
categories.Add(db.Categories.Where(c=>c.CategoryId==selectedCat).FirstOrDefault());

db.Posts.Add(new Post
{
PostId = C.p.PostId,
PostContent = C.p.PostContent,
PostTitle = C.p.PostTitle,
Categories = categories
});

db.SaveChanges();
return RedirectToAction("Index", "Home");
}

return View(C);
}

Chyba wygląda dość jasno co się dzieje :)

Uwagi mile widzianeSebastian O. edytował(a) ten post dnia 11.07.11 o godzinie 13:28

Temat: MVC 3 - Relacja wiele do wielu - EntityFramework

Super,
Masz może widok, gdzie edytujesz posta?
Dziękuję

Następna dyskusja:

ASP.NET MVC




Wyślij zaproszenie do