Entity Framework zamiast dopisywać relację to dodaje nową wartość

0

Witam ponownie. Proszę wybaczyć za niejasną nazwę tematu, ale ciężko to ująć w kilku słowach.

Mam powiedzmy tabelę klienci oraz tabelę województwa. Kiedy dodaję klienta, wybieram z listy województwo i dodaję do bazy klienta i w polu VoivodeshipId powinno być id województwa. Ale tylko w teorii. W praktyce jest tak, że jeśli wybiorę z listy przy dodawaniu Mazowieckie, to klient doda się z Mazowieckim, ale województwo mazowieckie również doda się jako kolejne do tabeli. Czy to jest normalne?
We ViewModelu mam dodawanie klienta prosto:

private void ExecuteSaveClient(Window window)
        {
            Client.CreatedDate = DateTime.Now;
            clientService.AddClient(Client);
            eventAggregator.GetEvent<ClientAddedEvent>().Publish("Klient został dodany");
            window.Close();
        }

W xamlu mam tak:

<ComboBox HorizontalAlignment="Left" Height="23" Margin="115,383,0,0" ItemsSource="{Binding Voivodeships}" DisplayMemberPath="Name" SelectedItem="{Binding Client.Voivodeship}" VerticalAlignment="Top" Width="185" SelectedIndex="0"/>

Czyli do klienta przypisuję cały obiekt typu województwo, z List<Voivodeship>, którą zainicjalizowałem w konstruktorze ViewModelu.

public class ClientDTO : IDataErrorInfo
    {
        public int Id { get; set; }
       [.....]
        public string Address1 { get; set; }
        public string Address2 { get; set; }
        public string PostalCode { get; set; }
        public string PostCity { get; set; }
        public string City { get; set; }
        public string Community { get; set; }
        public string County { get; set; }
        public VoivodeshipDTO Voivodeship { get; set; }
        public string PhoneNumber1 { get; set; }
        public string PhoneNumber2 { get; set; }
        public string Email { get; set; }
        public string Comments { get; set; }
[.....]


    }

I teraz tak, w ClientDTO mam dla województwa tylko obiekt typu VoivodeshipDTO, nie mam pola id dla województwa.

W serwisie mam:

public void AddClient(ClientDTO clientDto)
        {
            db.Clients.Add(Mapper.Map<ClientDTO, Client>(clientDto));
            db.SaveChanges();
        }

Mapowanie standardowe bez żadnego ręcznego definiowania.

I teraz tak, moje podejrzenia.

Jedną z moim zdaniem opcji może być to, że zapisuję do pola typu Client cały obiekt województwa, a nie samo Id. Nie wiem czy to jest normalnie, że tak by się działo, może jest normalne jeśli połączy się to z drugim podejrzeniem, mianowicie może chodzi o to, że listę województw pobieram serwisem VoivodeshipService, gdzie mam inną instancję db contextu niż w klasie, która zapisuje klienta.

Czy ktoś ma jakieś sugestie?

0

Całą operację (inaczej mówiąc unit of work) powinieneś wykonywać na jednej instancji contextu i z niej powinny pochodzić wszystkie obiekty, które odczytujesz/zapisujesz. Jeśli nie chcesz tak, to w ogóle nie używaj ORMa, bo tylko będzie Ci przeszkadzał.

0

Ok, nie powiedziałem, że nie chcę, po prostu wcześniej nie korzystałem z tego wzorca. Mógłbyś mnie jakoś nakierować jak to można u mnie zaimplementować? Mam zrobić sobie generyczne repozytorium czy o coś innego Tobie chodzi? Wybacz za takie pytanie, ale pierwszy raz mam z tego korzystać.

0

No napisz sobie w jakimś serwisie, jakąś metodę, która przyjmie dane podane przez użytkownika, w tej metodzie na podstawie id województwa pobierz województwo z bazy, utwórz rekord klienta, przypisz to pobrane województwo do tego rekordu i zatwierdź zmiany.

0

Wiesz co, mógłbym w sumie tak zrobić. Zrobiłem to w sumie poza serwisem, nie znam wzorców, ani tak dobrze jak inni dobrych praktyk w programowaniu, więc możliwe, że to co zrobiłem to głupie.

cfg.CreateMap<ClientDTO, Client>()
                    .ForMember(dest => dest.VoivodeshipId,
                    opts => opts.MapFrom(src => src.Voivodeship.Id))
                    .ForMember(dest => dest.Voivodeship, opts => opts.Ignore());

Teoretycznie mógłbym tutaj zostawić standardowe mapowanie i w serwisie zrobić tak:

public void AddClient(ClientDTO clientDto)
        {
            var clientToAdd = Mapper.Map<ClientDTO, Client>(clientDto);
            clientToAdd.Voivodeship = db.Voivodeships
                .Single(v => v.Id == clientDto.Voivodeship.Id);
            db.Clients.Add(clientToAdd);
            db.SaveChanges();
        }

Chyba największą różnicą w strukturze wstawianego obiektu jest to, że w pierwszym przypadku mam tylko id województwa a samo pole Voivodeship mam null, a w drugim mam w Voivodeship już obiekt. Pytanie, jak bardzo bez sensu jest rozwiązanie z modyfikacją mapowania ;)

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