Problem z zapisem do tabeli łączącej w relacji wiele do wiele w MVC

0

Witam serdecznie,

W modelu mam 3 tabele w relacji wiele do wiele

 ```
 public class Zlecenia
{
    [Key]
    //Relacja z tabelą ZleceniaZalaczniki.  
    public int IdZlecenia { get; set; }
    public string UserId { get; set; }
    public virtual Uzytkownik User { get; set; }
    public int IdZlecenieZalacznik { get; set; }
    public virtual ZleceniaZalaczniki ZleceniaZalaczniki { get; set; }
    public virtual ICollection<Pracownik> Pracownik { get; set; }

    [Required(ErrorMessage = "Podaj datę przyjecia zlecenia")]
    [Display(Name = "Data przyjęcia zlecenia")]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    public DateTime DataPrzyjeciaZlecenia { get; set; }
    [Display(Name = "Data planowania zakończenia")]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    public DateTime? DataPlanowaniaZakonczenia { get; set; }
    [Display(Name = "Data zakończenia")]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    public DateTime? DataZakonczenia { get; set; }
    [Required(ErrorMessage = "Wpisz temat")]
    [MaxLength(200, ErrorMessage = "Nazwa powinna zawierać max 200 znaków")]
    [Display(Name = "Temat")]
    public string Temat { get; set; }
    public string NazwaStanowiska { get; set; }
    // Relacja z tabelą Usługi
    [Required(ErrorMessage = "Wybierz usługę")]
    public int IdUslugi { get; set; }
    public virtual Uslugi Uslugi { get; set; }
    // Relacja z tabelą Zlecenia
    public int IdStatusZlecenia { get; set; }
    public virtual StatusZlecenia StatusZlecenia { get; set; }
    public virtual ICollection<ZleceniaLacznikPozycje> ZleceniaLacznikPozycje { get; set; }
public class ZleceniaLacznikPozycje
    {
        [Key]
        public int IdZleceniaLacznikPozycje { get; set; }
        public int IdZlecenia { get; set; }
        public int IdZleceniaPozycje { get; set; }
        public virtual Zlecenia Zlecenia { get; set; }
        public virtual ZleceniaPozycje ZleceniaPozycje { get; set; }
    }
public class ZleceniaPozycje
    {
        [Key]
        public int IdZleceniaPozycje { get; set; }
        [Column(TypeName = "nvarchar(MAX)")]
        [Display(Name = "Opis")]
        [UIHint("tinymce_jquery_full"), AllowHtml]
        public string Opis { get; set; }
        public virtual ICollection<ZleceniaLacznikPozycje> ZleceniaLacznikPozycje { get; set; }
    }

W kontrolerze w metodzie dodającej nowe zlecenie chce zapisać do bazy w powyższych tablicach dane. W zamyśle do każdego zlecenia będzie można dodać kilka postów - dlatego potrzebna jest relacja wiele do wiele

public ActionResult UtworzZlecenie()
        {
            DaneZleceniaUzytkownikaViewModel viewModels = new DaneZleceniaUzytkownikaViewModel();
            ViewBag.Czas = DateTime.Now;
            viewModels.DataPrzyjeciaZlecenia = DateTime.Now;
            viewModels.UsługiSelectListItem = new SelectList(db.Uslugi.Where(x => x.CzyAktywny == true), "IdUslugi", "NazwaUslugi");
            viewModels.StatusyZleceńSelectListItem = new SelectList(db.StatusZlecenia.Where(p => p.CzyAktywny == true && p.NazwaStatutuZlecenia == "Rejestracja"), "IdStatusZlecenia", "NazwaStatutuZlecenia");

            return View(viewModels);
        }
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult UtworzZlecenie(HttpPostedFileBase plik, DaneZleceniaUzytkownikaViewModel viewModel)
    {
        var userId = User.Identity.GetUserId();
      //  var znajdzUserId = db.Zlecenia.SingleOrDefault(i => i.UserId == userId);
        viewModel.UsługiSelectListItem = new SelectList(db.Uslugi, "IdUslugi", "NazwaUslugi");
        viewModel.StatusyZleceńSelectListItem = new SelectList(db.StatusZlecenia, "IdUslugi", "NazwaUslugi");

        if (ModelState.IsValid)
        {
            if (plik != null && plik.ContentLength > 0)
            {
                string sciezka = "/Content/Layout/FirmaPliki";
                if (!Directory.Exists(HttpContext.Server.MapPath(sciezka)))
                {
                    Directory.CreateDirectory(HttpContext.Server.MapPath(sciezka));
                }
                string filename = Path.GetFileName(plik.FileName);
               
                plik.SaveAs(Path.Combine(HttpContext.Server.MapPath(sciezka), filename));
                viewModel.NazwaPliku = sciezka + "/" + filename;

                //var nazwaPliku = Path.GetFileName(plik.FileName);

                //var path = Path.Combine(Server.MapPath("/Content/Layout/FirmaPliki"), nazwaPliku);

                //plik.SaveAs(path);

            }


            var zlecenie = new Zlecenia()
            {
                DataPrzyjeciaZlecenia = viewModel.DataPrzyjeciaZlecenia,
                Temat = viewModel.Temat,                 
                IdUslugi = viewModel.IdUslugi,
                IdStatusZlecenia = viewModel.IdStatusZlecenia,
                UserId = userId

            };

          

            var zleceniePozycje = new ZleceniaPozycje()
            {
                Opis = viewModel.Opis
            };

      

            var zlecenieZalacznik = new ZleceniaZalaczniki()
            {
                NazwaPliku = viewModel.NazwaPliku,
                Opis = viewModel.Opis2
            };

            db.Zlecenia.Add(zlecenie);
            db.ZleceniaPozycje.Add(zleceniePozycje);
            db.ZleceniaZalaczniki.Add(zlecenieZalacznik);
            db.SaveChanges();
      
        }
        return RedirectToAction("Index", "Administracja");
    }
Moje pytanie jest w jaki sposób zapisywać dane do tablicy ZleceniaLacznikPozycje z kluczami obcymi. 
Rozumiem że najpierw powinienem zapisywać dane w tablicy Zlecenia i ZleceniaPozycje.
Następnie mając dwa klucze z tych tablic powinienem je odczytać i  przesyć  do tablicy ZleceniaLacznikPozycje jako klucze obce  gdzie zostaną zapisane.
Jak powinien wyglądać zapis takich instrukcji?
0

Nie zwróciłem wcześniej uwagi na tag entity framework. Trochę szerokie pytanie... Ogólnie to za zapis do db odpowiada framework.
EF tworzyłes jako db first? Cross tabele sa wtedy tak optymalizowane przez EF, że.. ich nie ma. Nastręcza to czasem kilku można powiedzieć.. problemów. Navigation Properties nie są w zasadziie do relacji "many to many". Można to obejść przez brzydkie dodanie w db do tabeli łącznik (jak ją nazwałeś) sztucznego pola. Wtedy nie będzie optymalizacji, ale są inne wady tego rozwiązania.
EF code first? To aby uzyskać relację wiele do wielu musisz do swojej tabeli łącznik dodać metody/ę która definiuje relacje.
Myślę że najlepiej jesli poczytasz trochę sam.
[]https://stackoverflow.com/questions/19342908/how-to-create-a-many-to-many-mapping-in-entity-framework
[]http://www.c-sharpcorner.com/UploadFile/219d4d/working-with-multiple-tables-in-mvc-using-entity-framework/
To tylko jakieś tam przykładowe linki. Na necie znajdziesz sporo w tym temacie.

0

Tak tabele były tworzone przez First Code (uaktualniana baza przez migracje) lubię to podejście ponieważ mam wtedy pełną kontrolę nad tym co się znajduje w tabeli z poziomu Visual Studio.

Czy w moim przypadku wymagane jest zdefiniowanie poniższych relacji? Co jeszcze muszę dodać? Pytam ponieważ robię to pierwszy raz - jak poznam mechanizm to później już będę wiedział.

modelBuilder.Entity<ZleceniaLacznikPozycje>()
       .HasKey(c => new { c.IdZlecenia , c.IdZleceniaPozycje });

   modelBuilder.Entity<Zlecenia>()
       .HasMany(c => c.Temat)
       .WithRequired()
       .HasForeignKey(c => c.IdZlecenia );

   modelBuilder.Entity<ZleceniaPozycje>()
       .HasMany(c => c.Opis )
       .WithRequired()
       .HasForeignKey(c => c.IdZleceniaPozycje ); 
0

Tak na szybko, czas goni. Relacje wygladaja ok, w klasach Zlecenia i ZleceniaPozycje dodaj po kolekcji <ZleceniaLacznikPozycje>. Jesli sie nie myle to trzeba/można też było dodać w kontekście DbSet od kazdej z klas a w kazdej klasie miec kolekcje tej drugiej.

0

Bardzo dziękuję za wszystkie sugestie - DbSet dla każdej tabeli mam już utworzony. Dodam do każdej klasy kolekcje drugiej klasy.
Jak później w kontrolerze w metodzie UtworzZlecenie tworzyć obiekt z kluczami obcymi do tabeli Zlecenialacznikpozycje ?

0

Tak na początek, to ja bym się zastanowił, czy chcę używać ORM, czy pisać dane do tabel i ustawiać klucze obce. Bo to jest mieszanie dwóch poziomów abstrakcji i pewnie dlatego nie działa.

0
somekind napisał(a):

Tak na początek, to ja bym się zastanowił, czy chcę używać ORM, czy pisać dane do tabel i ustawiać klucze obce. Bo to jest mieszanie dwóch poziomów abstrakcji i pewnie dlatego nie działa.

Jak na razie mapowania nie zastosowałem - dostałem tylko sugestie od użytkownika 4programmers.net że tak można. Dla mnie najważniejsze jest podejście Code First które jest czytelne.

1 użytkowników online, w tym zalogowanych: 0, gości: 1