EF Core - W jaki sposób pobrać nazwy plików z tableli

0

Jestem początkujący w programowaniu.
Głowię się od dwóch dni w jaki sposób mogę wyświetlić wszystkie dane samochodu wraz ze zdjęciami o określonym id. Już mi powoli psycha siada. xd
Mam tabelę "Cars" oraz "CarImages" (tutaj są przechowywane zdjęcia samochodów)
Tak wygląda model Car

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace autoleasing.Models
{
    [Table("Cars")]
    public class CarModel
    {
        [Key]
        public int Id { get; set; }
        public string Brand { get; set; }
        public string BodyType { get; set; }
        public string GearboxType { get; set; }
        public string ProductionYear { get; set; }
        public string Mileage { get; set; }
        public string EnginePower { get; set; }
        public string EngineCapacity { get; set; }
        public string FuelType { get; set; }
        public int Count { get; set; }
        public bool Available { get; set; }
        public List<CarImage> AllImages { get; set; }
    }
}

A tak wygląda model CarImage

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace autoleasing.Models
{
    public class CarImage
    {
        [Key]
        public int Id { get; set; }
        public string ImageName { get; set; }
        [ForeignKey("CarModel")]
        public int CarId { get; set; }
        public CarModel CarModel { get; set; }
    }
}

Tak prezentuje się DetailsViewModel

using autoleasing.Models;

namespace autoleasing.ViewModels
{
    public class DetailsViewModel
    {
        public int Id { get; set; }
        public string Brand { get; set; }
        public string BodyType { get; set; }
        public string GearboxType { get; set; }
        public string ProductionYear { get; set; }
        public string Mileage { get; set; }
        public string EnginePower { get; set; }
        public string EngineCapacity { get; set; }
        public string FuelType { get; set; }
        public int Count { get; set; }
        public bool Available { get; set; }
        public List<CarImage> Images { get; set; }
    }
}

W CarRepository w ten sposób pobieram dane samochodu o podanym Id

        public CarImage GetById_test(int id)
        {
            return _context.CarImages.Include(p => p.CarModel).FirstOrDefault(x => x.CarId == id);
        }

W ten sposób próbuję w kontrolerze zmapować dane z modelu do viewmodelu (zapewne jest to źle, ale no już pokażę moje wypociny)

        [Route("Cars/Details/{id}")]
        [HttpGet]
        public ActionResult Details(int id)
        {
            var carImage = _carRepository.GetById_test(id);

            if (carImage == null) return View("Error");

            var list = new List<CarImage>();
            foreach (var img in carImage.ImageName)
            {
                list.Add(new CarImage( { ImageName = img });
            }

            var carVM = new DetailsViewModel
            {
                Brand = carImage.CarModel.Brand,
                BodyType = carImage.CarModel.BodyType,
                GearboxType = carImage.CarModel.GearboxType,
                ProductionYear = carImage.CarModel.ProductionYear,
                Mileage = carImage.CarModel.Mileage,
                EnginePower = carImage.CarModel.EnginePower,
                EngineCapacity = carImage.CarModel.EngineCapacity,
                FuelType = carImage.CarModel.FuelType,
                Count = carImage.CarModel.Count,
                Available = carImage.CarModel.Available,
                Images = list
            };

            return View(carVM);
        }

Jaki sposób mogę wyświetlić wszystkie dane samochodu wraz ze zdjęciami o określonym id?

1

Do view modelu prześlij jedynie id obrazu. Stwórz akcję w kontrolerze która przyjmuje id i zwraca plik. Mając listę identyfikatorów możesz teraz zbudować URL który przeklejasz do src i tyle :)

0

Udało mi się w końcu rozwiązać problem.
W CarRepository utworzyłem taką akcję, którą również zaimplementowałem w interfejsie

public IEnumerable<CarImage> GetImagesByCar(int carid)
{
      return _context.CarImages.Where(c => c.CarId == carid);
}

W DetailsViewModel podmieniłem "List" na "IEnumerable"

public IEnumerable<CarImage> Images { get; set; }

Tak wygląda mój kontroler

[Route("Cars/Details/{id}")]
        [HttpGet]
        public ActionResult Details(int id)
        {
            var carImages = _carRepository.GetImagesByCar(id);
            var carModel = _carRepository.GetById(id);

            if (carModel == null) return View("Error");


            var carVM = new DetailsViewModel
            {
                Brand = carModel.Brand,
                BodyType = carModel.BodyType,
                GearboxType = carModel.GearboxType,
                ProductionYear = carModel.ProductionYear,
                Mileage = carModel.Mileage,
                EnginePower = carModel.EnginePower,
                EngineCapacity = carModel.EngineCapacity,
                FuelType = carModel.FuelType,
                Count = carModel.Count,
                Available = carModel.Available,
                Images = carImages
            };

            return View(carVM);
        }

No i w widoku pętla foreach i działa.

0

Z tego co sam się uczyłem to nie powinno się zwracać bez wyraźnej potrzeby iqueryable. Zamiast tego możesz na końcu po where dać toList()

0
gswidwa1 napisał(a):

Z tego co sam się uczyłem to nie powinno się zwracać bez wyraźnej potrzeby iqueryable. Zamiast tego możesz na końcu po where dać toList()

Hmm. Ciekawe. A mógłbyś uargumentować dlaczego powinno się dodawać.ToList()?

0

Bo to zwykle bez sensu jest?
Bo IQuaryable jest lazy i, w ogólnym przypadku, możesz już nie mieć połączenia do DB jak zechcesz użyć danych?

W Twoim przykładzie to przejdzie ale ogólnie to można się zdziwić.

OT. Tak z ciekawości to Twój Car nie wie jakie ma Images, że się pytasz 2 razy?

0
jacek.placek napisał(a):

Bo to zwykle bez sensu jest?
Bo IQuaryable jest lazy i, w ogólnym przypadku, możesz już nie mieć połączenia do DB jak zechcesz użyć danych?

W Twoim przykładzie to przejdzie ale ogólnie to można się zdziwić.

OT. Tak z ciekawości to Twój Car nie wie jakie ma Images, że się pytasz 2 razy?

Okej, rozumiem.
Z mojego punktu widzenia nie wie jakie ma Images - po prostu nie wiem jak zrobić by pytało tylko raz.

Jeżeli wiesz jak to zrobić to wcale się nie pogniewam lepszym rozwiązaniem. 😂 Cały model jest w pierwszym poście tego tematu.

2

Tworzysz modele

public class CarModel
    {
        public Guid Id { get; set; }
        public string Brand { get; set; }
        public string BodyType { get; set; }
        public string GearboxType { get; set; }
        public string ProductionYear { get; set; }
        public string Mileage { get; set; }
        public string EnginePower { get; set; }
        public string EngineCapacity { get; set; }
        public string FuelType { get; set; }
        public int Count { get; set; }
        public bool Available { get; set; }
        public virtual List<CarImage> CarImages { get; set; }
    }
    public class CarImage
    {
        public Guid Id { get; set; }
        public string ImageName { get; set; }
        public Guid CarModelId { get; set; }
    }

Dodajesz tabele do konteksu

public class ApplicationDbContext : DbContext
    {
        public DbSet<CarModel> CarModels { get; set; }
        public DbSet<CarImage> CarImages { get; set; }

Tworzysz metodę w serwisie:

public async Task<CarModel> GetCarModelOrNull(Guid id)
        {
            return await dbContext
                .CarModels
                .Include(x => x.CarImages)
                .FirstOrDefaultAsync(x => x.Id == id);
        }

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