Niepełne dane z bazy

0

Cześć,

Mam następujący kod, który pobiera mi dane firmy z bazy:

public Company GetCompany(string UserId)
        {
            var company = _context.Companies.Where(c => c.UserId == UserId).FirstOrDefault();
            return company;
        }

Tak wygląda klasa Company

    public class Company
    {
        public int Id { get; set; }
        [Required]
        [MaxLength(50)]
        public string Name { get; set; }
        [MaxLength(200)]
        public string PhotoFilePath { get; set; }
        public string UserId { get; set; }
        public Address Address { get; set; }
        public List<Workplace> Workplaces { get; set; }

    }

Niestety dane, które są pobierane to tylko: Id, Name, PhotFilePath oraz UserId. Nie pobiera mi danych obiektu Address, mimo że na bazie mam kolumnę z Id uzupełnioną:
baza.PNG

Ponadto gdy aktualizuję dane, EF tworzy mi kolejny rekord w tabeli Address zamiast zaktualizować ten, który jest już przypisany do firmy.

2

var company = _context.Companies.Include(x => x.Address).Where(c => c.UserId == UserId).FirstOrDefault();

https://www.entityframeworktutorial.net/eager-loading-in-entity-framework.aspx lub włącz lazy loading

a tu jak skonfigurować relacje https://www.entityframeworktutorial.net/code-first/configure-property-mappings-using-fluent-api.aspx

0

@boska_cebula: dobrze rozumiem, że fluent api pozwala na takie skonfigurowanie DBContext, że mógłbym dzięki temu uniknąć znacznej części mapowań? Przynajmniej z tego co doczytałem tak wynika... Między innymi oczywiście. Zaraz biorę się za praktykę :)

1

Chodzi o to że dostosowujesz swój obiekt do tego jak ma wyglądać lub jak wygląda obiekt SQL.
Mapowanie w architekturze aplikacji pomiędzy warstwami to zupełnie inna kwestia niezwiązana z tym

0

Ok pobiera mi się teraz cały obiekt, więc jest jak należy.

Problem
Przemodelowałem nieco relację i teraz wygląda to następująco. Chcę zaktualizować dane firmy. Dane firmy to tak na prawdę w tej chwili tylko Nazwa, PhotoFilePath i UserId, natomiast istnieje relacja do Addresses, gdzie jest kolumna AddressObjectId, w której przechowuję Id firmy. Obecnie nie aktualizują mi się dane w tabelach powiązanych mimo iż w obiekcie je wysyłam. Co ważne, podczas dodawania nowej firmy do bazy, nie musi ona mieć adresu, użytkownik może go dodać później.

Co chcę osiągnąć
W momencie gdy istnieje AddressObjectId w tabeli Addresses - zaktualizować go, a jeśli nie - dodać nowy adres.

Mój kod update

        public Company UpdateCompany(Company companyChanges)
        {
            _context.Entry(companyChanges).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
            _context.SaveChanges();
            return companyChanges;
        }
0

Nieco przemodelowałem metodę, ale nadal to nie jest to. Otrzymuję ex:
ex.PNG

Poniżej moja metoda:

        public Company UpdateCompany(Company companyChanges)
        {
            if (companyChanges == null)
            {
                return null;
            }

            var dbCompany = _context.Companies
                .Include(x => x.Address)
                .SingleOrDefault(c => c.Id == companyChanges.Id);

            _context.Entry(dbCompany).CurrentValues.SetValues(companyChanges);
            _context.Entry(dbCompany.Address).CurrentValues.SetValues(companyChanges.Address);
            _context.SaveChanges();
            return companyChanges;
        }

EDIT:
@boska_cebula konfiguracja jest zgodna z tym co wskazane w https://www.entityframeworktutorial.net/efcore/one-to-one-conventions-entity-framework-core.aspx. Moja klasa Address:

    public class Address
    {
        public int Id { get; set; }
        [Required]
        [MaxLength(20)]
        [Column(TypeName = "varchar(20)")]
        public string PostalCode { get; set; }

        [MaxLength(50)]
        public string Street { get; set; }
        [MaxLength(10)]
        public string StreetNumber { get; set; }
        [MaxLength(10)]
        public string ApartmentNumber { get; set; }
        [ForeignKey("Company")]
        public int? AddressOfCompanyId { get; set; }
        public virtual Company Company { get; set; }
        [ForeignKey("Workplace")]
        public int? AddressOfWorkplaceId { get; set; }
        public virtual Workplace Workplace { get; set; }
        public int? CityId { get; set; }
        public City City { get; set; }
    }

oraz Company:

    public class Company
    {
        public int Id { get; set; }
        [Required]
        [MaxLength(50)]
        public string Name { get; set; }
        [MaxLength(200)]
        public string PhotoFilePath { get; set; }
        public string UserId { get; set; }
        public Address Address { get; set; }
        public List<Workplace> Workplaces { get; set; }
    }
0

Czemu służy ustawianie wartości w ten sposób?

_context.Entry(dbCompany).CurrentValues.SetValues(companyChanges);
_context.Entry(dbCompany.Address).CurrentValues.SetValues(companyChanges.Address);

To jest EF czy EF Core? bo tag jedno, a kod EntityFrameworkCore drugie.

1

A sprawdziłeś chociaż, czy nie zerujesz/nadpisujesz klucza głównego?

0

Sprawdź tak:

public Company UpdateCompany(Company companyChanges)
{
  if (companyChanges == null) return default;

  _context.Update(companyChanges)
  _context.SaveChanges();

  return companyChanges;
}
0

@urke: chyba masz rację,wydaje mi się, że mapowanie w jakiś sposób nadpisuje Id na 0, ale nie wiem dlaczego:
zmienn.PNG

Tak wygląda mapowanie z modelu do entity:

            CreateMap<CompanyDetailsViewModel, Company>()
                .ForPath(dto => dto.Address.PostalCode, opt => opt.MapFrom(src => src.PostalCode))
                .ForPath(dto => dto.Address.CityId, opt => opt.MapFrom(src => src.SelectedCity))
                .ForPath(dto => dto.Address.Street, opt => opt.MapFrom(src => src.Street))
                .ForPath(dto => dto.Address.StreetNumber, opt => opt.MapFrom(src => src.StreetNumber))
                .ForPath(dto => dto.Address.ApartmentNumber, opt => opt.MapFrom(src => src.ApartmentNumber))
                .ForMember(dto => dto.Workplaces, opt => opt.MapFrom(src => src.Workplaces))
                .ForMember(dto => dto.UserId, opt => opt.MapFrom(src => src.UserId))
                .ForMember(dto => dto.Id, opt => opt.Ignore());
0

Dodaj w obiekcie int? To pozwoli przybrać mu wartość null

0

W sumie to pytanie. Czy jeżeli w ViewModelu mam CompanyId, które pobieram z bazy, to przy wysłaniu posta to pole powinno znaleźć się na widoku, ale jako ukryte? Czy mimo to po wysłaniu żądania nadal będzie ono z tą wartością?

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