Wyświetlanie produktów według kategorii

0

Cześć

mam pytanie natury technicznej.

Mam widok główny w swojej aplikacji zawierający zdjęcia wybranych kategorii produktów. Chciałbym aby po kliknięciu w zdjęcie np. Pieczywa wyświetliły mi się wszystkie produkty z kategorii Pieczywo.

W widoku głównym na sztywno ustaliłem sobie new {Name="Pieczywo"}

 
 <a href="@Url.Action("Index","Category", new {Name="Pieczywo"})">
        <img class="img-responsive" src="~/Content/Images/Mainpage/Categories/pieczywo.jpg" alt="Pieczywo">
 </a>

Zrobiłem sobie ViewModel do wyświetlania pol produktu.

Potem stworzyłem sobie CategoryController który posiada akcję Index przyjmującą parametr string categoryName

 
public ActionResult Index(string categoryName)
        {
            using (var db = new ApplicationDbContext())
            {
                var selectedcategory = db.ProductCategories.FirstOrDefault(c => c.Name == categoryName);

                var q = db.Products.Where(x => x.Category.Contains(selectedcategory)).Select(r => new ProductDisplayViewModel()
                {
                    Id = r.Id,
                    ProductName = r.ProductName,
                    ProductDescription = r.ProductDescription,
                    ProductPrice = r.PricePerUnit,
                    ProductQuantity = r.Quantity
                });

                return View(q.ToList());
            }
            return View();
        }

Następnie widok do wyświetlania:

 

@model IEnumerable<SklepInternetowy.ViewModels.ProductDisplayViewModel>
@{
    ViewBag.Title = "Produkty";
}

<h2>Produkty dla wybranej kategorii</h2>

<br />
<div>
    <table class="table table-striped table-bordered table-condensed">
        <thead>
            <tr>
                <th>ID</th>
                <th>Nazwa produktu</th>
                <th>Opis produktu</th>
                <th>Cena za sztuke</th>
                <th>Ilość sztuk w magazynie</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model)
            {
                <tr>
                    <td>@item.Id</td>
                    <td>@item.ProductName</td>
                    <td>@item.ProductDescription</td>
                    <td>@item.ProductPrice</td>
                    <td>@item.ProductQuantity</td>
                </tr>
            }
        </tbody>
    </table>
    <br /><br /><br />
    <br /><br /><br />

</div>

Nie działa mi to bo po kliknięciu w wybraną kategorię otrzymuję błąd:

The specified type member 'Quantity' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

Wiersz 24:                 });
Wiersz 25: 
Wiersz 26:                 return View(q.ToList()); // tutaj podczas zwracania listy
Wiersz 27:             }
Wiersz 28:             return View();
 

Co robie zle? Jak sobie z tym poradzic?

0

domyslam ze sie Quantity jest metoda, ktora wylicza to quantity na podstawie czegos, a nie mozna tego robic na poziomie zapytania do entity

0

Nie. Quantity to ilość sztuk danego produktu. Nie metoda. I chciałbym wyświetlić tę ilość.

Ciekawe jest to, że jak wygeneruje sobie ProductController z modelem Productu to nie ma żadnego problemu żeby to wyświetlić.

0
  1. Jeżeli robisz
 
...new {Name = "Pieczywo"}

to wydaje mi się (piszę tak ponieważ wiem na 100% że w jakimś przypadku tak trzeba zrobić, ale nie wiem czy to jest właśnie ten) że w kontrolerze w akcji index też musisz tak samo nazwać zmienną:

public ActionResult Index(string Name)
  1. Następna rzecz (też nie jestem pewien ale warto sprawdzić):
 return View(q.ToList());

a potem w widoku masz:

@model IEnumerable<SklepInternetowy.ViewModels.ProductDisplayViewModel>

wysyłasz listę do czegoś co oczekuje IEnumerable

Oprócz tego myślę że tutaj znajdziesz też odpowiedź....:
http://stackoverflow.com/questions/26929708/displaying-products-from-database-to-view-by-product-ctegory :/

0

Poprawiłem tą nazwe parametru w akcji i teraz błą jest inny:

Unable to create a constant value of type 'Myproject.Models.ProductCategory'. Only primitive types or enumeration types are supported in this context.

Natomiast to IEnumerable<> chyba musi być no bo mam wiele produktów i potem w widoku mam foreacha w którym wyświetlam kolejne pola z ViewModelu

Okazuje się, że problem jest troche inny. Moja tabela Product nie posiada pola Quantity. Nie wiem czemu Code first mi tego pola nie wygenerowal :/

Więc korzystam z Identity czyli tego domyślnego membershipa i tam jest ApplicationDbContext

Więc dopisałem sobie swoje DbSety<> żeby wygenerowały sie do tego samego COntextu a poniżej mam fluentMapping

 public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IDisposable
    {
        public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {
            
        }

        // moje dodatkowe tabele, które beda generowane przez code first
        public DbSet<Product> Products { get; set; }
        public DbSet<ProductCategory> ProductCategories { get; set; }
        public DbSet<NutritionalValue> NutritionalValues { get; set; }
        public DbSet<Customer> Customers { get; set; }
        public DbSet<Addresses> Addresseses { get; set; }
        public DbSet<Order> Orders { get; set; }
        public DbSet<OrderDetail> OrderDetails { get; set; }
        public DbSet<Suplier> Supliers { get; set; }

        // mapowanie przy uzyciu fluent mapping
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

            // ustalenie kluczy dla poszczególnych modeli
            modelBuilder.Entity<Addresses>().HasKey(a => a.Id);
            modelBuilder.Entity<Product>().HasKey(a => a.Id);
            modelBuilder.Entity<ProductCategory>().HasKey(a => a.Id);
            modelBuilder.Entity<NutritionalValue>().HasKey(a => a.Id);
            modelBuilder.Entity<Customer>().HasKey(a => a.Id);
            modelBuilder.Entity<Order>().HasKey(a => a.Id);
            modelBuilder.Entity<OrderDetail>().HasKey(a => a.Id);
            modelBuilder.Entity<Suplier>().HasKey(a => a.Id);

            // definicj relacji pomiedzy modelami
            modelBuilder.Entity<Suplier>().HasMany(s => s.Address);

            modelBuilder.Entity<Product>().HasMany(p => p.Category);
            modelBuilder.Entity<Product>().HasMany(p => p.Supliers);
            modelBuilder.Entity<Product>().HasMany(p => p.OrderDetails);
            modelBuilder.Entity<Product>().HasRequired(p => p.NutritionalValues);

            modelBuilder.Entity<ProductCategory>().HasMany(p => p.Products);

            modelBuilder.Entity<OrderDetail>().HasMany(od => od.Products);
            modelBuilder.Entity<OrderDetail>().HasRequired(od => od.Order);

            modelBuilder.Entity<Order>().HasRequired(o => o.OrderDetail);
            modelBuilder.Entity<Order>().HasRequired(o => o.Customer);
            modelBuilder.Entity<Order>().HasMany(o => o.Products);

            modelBuilder.Entity<Customer>().HasMany(c => c.Addresses);
            modelBuilder.Entity<Customer>().HasMany(c => c.Orders);

            //modelBuilder.Entity<Addresses>().HasRequired(a => a.Customer);
            modelBuilder.Entity<Addresses>().HasMany(a => a.Suplier);

            
            base.OnModelCreating(modelBuilder);
        }

 
0

Problem rozwiązany dzięki @ne0. Należy mu się spory + :)

2

Dodam tutaj rozwiązanie żeby jak coś inni też mieli.

  1. Zamiast
 var q = db.Products.Where(x => x.Category.Contains(selectedcategory)).Select(r => new ProductDisplayViewModel()
                {
                    Id = r.Id,
                    ProductName = r.ProductName,
                    ProductDescription = r.ProductDescription,
                    ProductPrice = r.PricePerUnit,
                    ProductQuantity = r.Quantity
                });
 
                return View(q.ToList());

trzeba dać:

var q = db.Products.Where(x => x.Category.Any(y=> y.CategoryName == selectedcategory.Name)).Select(r => new ProductDisplayViewModel
                {
                    Id = r.Id,
                    ProductName = r.ProductName,
                    ProductDescription = r.ProductDescription,
                    ProductPrice = r.PricePerUnit,
                    ProductQuantity = r.ProductQuantity,
                    PremiumPoints = r.PremiumPoints
                });
  1. Widok powyższej akcji i tutaj chodzi o zmianę modelu:
@model List<ViewModels.ProductDisplayViewModel>
  1. Następnie we wszystkich klasach pozmieniać IQueryable na IEnumerable

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