Czy można odwołać się bezpośrednio do obiektu klasy wewnątrz innej klasy w Entity Framework?

0

Witam, wiem że tytuł jest bardzo mało zrozumiały ale tutaj postaram się to bardziej wytłumaczyć. O co mi chodzi:

Tworzę projekt na zajęcia na studiach i korzystam w nim z Entity Frameworka (6.4.0) mam w nim kilka encji, ale narazię chce się skupić na dwóch.

    public class Product : IEntity
    {
        public int ProductId { get; set; }
        public string ProductName { get; set; }
        public decimal Price { get; set; }
        public int StoreID { get; set; }
        public Store Store { get; set; }
    }

i

    public class Store : IEntity
    {
        public int StoreId { get; set; }
        public int AddressId { get; set; }
        public Address Address { get; set; }
        public ICollection<Product> Products { get; set; }
        public int ContractorId { get; set; }
        public Contractor Contractor { get; set; }
    }

Dalej mam obsłużone dodawanie i zwracanie wartości z bazy mam obsłużone i to działa poprawnie poza jedną rzeczą.
Kiedy staram się sięgnąć po Produkt i dalej do jego Sklepu i wybrać stamtąd jakąś wartość to Store jest nullem.

        static void Main(string[] args)
        {
            IProductService productManager = new ProductManager(new ProductDal());

            productManager.Add(new Product { ProductName = "Tangerines", Price = 50, ProductId = 1, Store = new Store() { Address = new Address(), Contractor = new Contractor() } });

            productManager.GetAll().ForEach(x => Console.WriteLine(x.Store.ContractorId)); //Tu jest null

            Console.ReadLine();
        }

W jaki sposób mogę się dostać do tej zmiennej? Myślałem że Entity Framework jakoś to połączy, ale w tym wypadku to niestety nie działa.

Za wszelką pomoc bardzo dziękuje :)

1

Można. Pewnie gdzieś tam pod spodem (w GetAll) brakuje Ci Include na Store

0
kzkzg napisał(a):

Można. Pewnie gdzieś tam pod spodem (w GetAll) brakuje Ci Include na Store

Własnie czytałem na internecie o tym Include tylko nie wiem, w której dokładnie części miałbym tego użyć. Metoda GetAll() jest generyczna i taka sama dla każdej klasy encji

        public List<TEntity> GetList(Expression<Func<TEntity, bool>> filter = null)
        {
            using (var context = new TContext())
            {
                if (filter != null)
                {
                    return context.Set<TEntity>().Where(filter).ToList();
                }

                return context.Set<TEntity>().ToList();
            }
        }

Dalej już jest klasa dziedzicząca i tam to już jest jako GetAll()

Też zauważę że korzystam z podejścia Code first więc baza jest tworzona przy pierwszym uruchomieniu programu

Wcześniej próbowałem tego użyć w klasie dziedziczącej po DbContext ale tam mi też zwracało błąd

1
  1. Sprawdź czy w bazie danych są odpowi3dnie klucze obce.
  2. Obiekty w klasach powinny być virtual. public virtual Store Store {het; set;}
  3. Jeśli masz jawny StoreId to trzeba skonfigurować użycie tego StoreId jako klucza obcego. Kiedyś domyślnie chyba gen3rował Store_id, z podkreśleniem.
  4. Użycie Include w zapytaniach, albo świadomie LazyLoading.
  5. Zacznij używać migracji.
  6. Ta genetyczna GwtAll chyba nigdy nie zwróci Ci podrzędnych obiektów. Nie Includujesz nic w zapytania A lazy loading nie zadziała bo już nie ma DbContext.
0

Aktualnie myślę nad napisaniem extension metody, która by mi pozwoliła zaincludować dowolną ilość i później w klasie dziedziczącej przekazywać te property, które są potrzebne dla każdej encji, ale nie wiem czy to jest wykonalne.

1

Wykonalne jest, ale...

Nic Ci to nie da jeśli w samym modelu bazy będziesz miał śmietnik.

Przykład poniżej. Tam jest jeszcze AsNoTracking, żeby wyłączyć śledzenie zmian w EF.
Powtórzę. migracje, konfiguracja modelu z FluentAPI i dopiero potem jakieś generyki i dalsza zabawa.

public virtual IList<T> GetAll(params Expression<Func<T, object>>[] navigationProperties)
        {
            List<T> list;
            using (var context = new DozowanieContext())
            {
                IQueryable<T> dbQuery = context.Set<T>();

                foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
                    dbQuery = dbQuery.Include<T, object>(navigationProperty);

                list = dbQuery
                    .AsNoTracking()
                    .ToList<T>();
            }
            return list;
        }

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