Pobieranie danych z bazy ASP.NET MVC - błąd

0

Robie sobie cwiczenie (na wzor z ksiazki Freemana) z pobieraniem danych z bazy ale dostaje błąd przy foreach :
object reference not set to an instance of an object

@foreach (var p in Model)
{
    Html.RenderPartial("List", p);
}

List

@model SystemZamowien.Entities.Product


    <div class ="item">
        <h3>@p.Opis</h3>
        @p.ModelProduktu
        <h4>@p.Cena.ToString("c")</h4>
    </div>

Repozytorium z bazy mam zrobione:

EFProductRepository

using SystemZamowien.Abstract;
using SystemZamowien.Entities;
using System.Linq;

namespace SystemZamowien.Concrete
{
    public class EFProductRepository : IProductRepository
    {
        private EFDbContext context = new EFDbContext();

        public IQueryable<Product> Produkty
        {
            get { return context.Produkty; }
        }
    }
}

Powiązania również:
EFDbContext

using SystemZamowien.Entities;
using System.Data.Entity;

namespace SystemZamowien.Concrete
{
    public class EFDbContext : DbContext
    {
        public DbSet<Product> Produkty { get; set; }
    }
}

i jeszcze akcja kontrolera:

namespace SystemZamowien.Controllers
{
    public class ProductController : Controller
    {
        private IProductRepository repository;

        public ProductController(IProductRepository productRepository)
        {
            this.repository = productRepository;
        }

        public ViewResult Index()
        {
            return View(repository.Produkty);
        }

    }
}

W czym może być problem? Poproszę o jakieś wskazówki.

0

Po pierwsze jako Model masz pojedynczy obiekt klasy Product

@model SystemZamowien.Entities.Product 

A dając pętlę foreach chcesz iterować po jakiejś kolekcji. Jeśli chcesz w widoku mieć listę obiektów klasy Product to musisz jako model mieć np. obiekt implementujący IEnumerable:

@model IEnumerable<SystemZamowien.Entities.Product> 

Po drugie gdzie przekazujesz obiekt do widoku? W akcji powinieneś go przekazać do funkcji View(). Czyli jak masz akcję, dla której piszesz widok to coś takiego powinno się w niej znaleźć:

var produkty = context.Produkty.ToList(); //załóżmy, że obiekt kontekstu nazywa się właśnie context i chcesz pobrać wszystkie produkty z bazy
//...
return View(produkty); 

EDIT: Ok, teraz zauważyłem, że z tym modelem to masz w partialView więc mój pierwszy punkt w sumie nieważny :P

0

No to teraz sobie ustaw debuggera i zobacz czy coś w ogóle Ci zwraca.

var produkty = repository.Produkty
return View(produkty);

zobacz sobie czy pod zmienną produkty masz jakie kolwiek wartości (i nie mów mi że w bazie masz :P zobacz czy są tutaj)

0
ne0 napisał(a):

No to teraz sobie ustaw debuggera i zobacz czy coś w ogóle Ci zwraca.

var produkty = repository.Produkty
return View(produkty);

zobacz sobie czy pod zmienną produkty masz jakiekolwiek wartości (i nie mów mi że w bazie masz :P zobacz czy są tutaj)

Zrobiłem to tak jak radziłeś ale dalej na foreachu to samo (nic nie zwraca) - błąd dalej jest :(
.
Product Controller:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SystemZamowien.Abstract;
using SystemZamowien.Entities;
using SystemZamowien.Models;
using SystemZamowien.Concrete;


namespace SystemZamowien.Controllers
{
    public class ProductController : Controller
    {
        private IProductRepository repository;

        public ProductController(IProductRepository productRepository)
        {
            this.repository = productRepository;
        }

        public ViewResult Index()
        {
            var productListing = repository.Produkty;
            return View(productListing);
        }

    }
}

Index.cs
@model IEnumerable<SystemZamowien.Entities.Product>

@{
    ViewBag.Title = "Home Page";
}
@section featured {
    <section class="featured">
        <div class="content-wrapper">
            <hgroup class="title">
                <h1>@ViewBag.Title</h1>
                <h2>@ViewBag.Message</h2>
            </hgroup>
            <p>
                Witaj ...............
            </p>
        </div>
    </section>
}
<h3>Produkty:</h3>
<ol class="round">
    <li class="one">
        <h5>Nasze produkty</h5>
       
    </li>
</ol>


@foreach (var p in Model)
{
    Html.RenderPartial("List", p);
}

Gdzie moze być jeszcze problem?

0
ne0 napisał(a):

No to teraz sobie ustaw debuggera i zobacz czy coś w ogóle Ci zwraca.

var produkty = repository.Produkty
return View(produkty);

zobacz sobie czy pod zmienną produkty masz jakie kolwiek wartości (i nie mów mi że w bazie masz :P zobacz czy są tutaj)

Dokładnie nic nie zwraca tak jak kolega niżej pisze;/

0

A do jakiej bazy sie łączysz i jak wyglada Twoj connection string?

0
FakeAccount napisał(a):

A do jakiej bazy sie łączysz i jak wyglada Twoj connection string?

Może gdzieś faktycznie jest problem przy łączeniu z bazą.

Connection string wygląda tak:

  <connectionStrings>
    <add name="EFDbContext" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=SystemZamowien;Integrated Security=True" providerName="System.Data.SqlClient"/>
  </connectionStrings>

Ewentualnie mam całość na Gicie, moge linka podrzucić.

0

do klasy ProductController dodaj coś takiego

        
public ProductController()
	: this(new EFProductRepository())
      {   }
0
wesek91 napisał(a):

do klasy ProductController dodaj coś takiego

        
public ProductController()
	: this(new EFProductRepository())
      {   }

W takiej postaci dalej ten sam błąd niestety.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SystemZamowien.Abstract;
using SystemZamowien.Entities;
using SystemZamowien.Models;
using SystemZamowien.Concrete;


namespace SystemZamowien.Controllers
{
    public class ProductController : Controller
    {
        public ProductController()
            : this(new EFProductRepository())
        { }

        private IProductRepository repository;

        public ProductController(IProductRepository productRepository)
        {
            this.repository = productRepository;
        }

        public ViewResult Index()
        {
           
            return View();
        }

    }
}
0
  1. Zmieniłem w web.config na:
  <provider invariantName="system.data.sqlclient" type="System.Data.Entity.SqlServer.SqlProviderServices, entityframework.sqlserver" />
  1. Nie masz nigdzie metody Seed, więć nie wiem skąd mają się brać te produkty. Miałeś błąd w /Fileters/InitializeSimpleMembershipAttribute: zmień sobie context żeby się zgadzał z nazwą Twojego connectionString.

Nie wiem o co chodzi z tą metodą Seed, nie wiem czemu nie czyta jej w ogóle, nie odpala się.

0
ne0 napisał(a):
  1. Zmieniłem w web.config na:
  <provider invariantName="system.data.sqlclient" type="System.Data.Entity.SqlServer.SqlProviderServices, entityframework.sqlserver" />
  1. Nie masz nigdzie metody Seed, więć nie wiem skąd mają się brać te produkty. Miałeś błąd w /Fileters/InitializeSimpleMembershipAttribute: zmień sobie context żeby się zgadzał z nazwą Twojego connectionString.

Nie wiem o co chodzi z tą metodą Seed, nie wiem czemu nie czyta jej w ogóle, nie odpala się.

Pozmieniałem ale dalej to samo. O którą metodę "Seed" Ci chodzi?

1

Wiem że dalej to samo bo napisałem że dalej to nie działa. O metodę którą sam napisałem: jest to metoda, która podczas kompilowania projektu zapełnia bazę danych jakimiś przykładowymi danymi (może ktoś tu się wypowie i uzupełni moją wypowiedzieć bo nie jestem pewien czy te dane trafiają do bazy czy są w jakiejś pamięci oraz czy to jest podczas kompilacji czy zaraz po kompilacji).
Chodzi o to abyś po prostu miał na czym testować ten projekt. ja głównie pracuje z NHibernate, ale miałem przyjemność tworzyć ze 2-3 projekty z EF i zawsze to działało tak jak robiłem. Jutro rano jeszcze na to zobaczę kolejny raz.

Nie ukrywam że mnie to wkur**** że nie umiem Ci z tym pomóc na razie :(

1

Okay zrobiłem.

  1. Tak wygląda HomeController:
  private readonly IProductRepository repository;

        public HomeController(IProductRepository pro)
        {
            this.repository = pro;
        }

        public ActionResult Index()
        {
           
            ViewBag.Message = "System Zamówimtgjfr eń";

            var k = repository.Produkty.ToList();
            return View(k);
  
        }
  1. W web.config Twój connectionString nazywa się "EFDbContext" dlatego w pliku AccountModels także musisz zmienić nazwę i początek powinien tak wyglądać:
 public UsersContext()
            : base("EFDbContext")
        {
        }
  1. Nie wiem czy to jest konieczne ale pozmieniałem te Twoje IQueryable na IEnumerable.

  2. Tak wygląda ProductRepository:

 public class EFProductRepository : IProductRepository
    {
        private readonly EFDbContext context = new EFDbContext();

        public EFProductRepository(EFDbContext context)
        {
            this.context = context;
        }

        public IEnumerable<Product> Produkty
        {
            get
            {
                return context.Produkty;
            }

        }

    }
  1. Ja podpiąłem swój MS SQL server w web.configu. Baza została wygenerowana, potem dodałem przykładowy produkt od ręki i został on pobrany do HomeController w funkcji
  var k = repository.Produkty.ToList();

Nie chciało mi się już bawić z widokiem: ale został ładnie do niego przesłany.

0
ne0 napisał(a):

Okay zrobiłem.

  1. Tak wygląda HomeController:
  private readonly IProductRepository repository;

        public HomeController(IProductRepository pro)
        {
            this.repository = pro;
        }

        public ActionResult Index()
        {
           
            ViewBag.Message = "System Zamówimtgjfr eń";

            var k = repository.Produkty.ToList();
            return View(k);
  
        }
  1. W web.config Twój connectionString nazywa się "EFDbContext" dlatego w pliku AccountModels także musisz zmienić nazwę i początek powinien tak wyglądać:
 public UsersContext()
            : base("EFDbContext")
        {
        }
  1. Nie wiem czy to jest konieczne ale pozmieniałem te Twoje IQueryable na IEnumerable.

  2. Tak wygląda ProductRepository:

 public class EFProductRepository : IProductRepository
    {
        private readonly EFDbContext context = new EFDbContext();

        public EFProductRepository(EFDbContext context)
        {
            this.context = context;
        }

        public IEnumerable<Product> Produkty
        {
            get
            {
                return context.Produkty;
            }

        }

    }
  1. Ja podpiąłem swój MS SQL server w web.configu. Baza została wygenerowana, potem dodałem przykładowy produkt od ręki i został on pobrany do HomeController w funkcji
  var k = repository.Produkty.ToList();

Nie chciało mi się już bawić z widokiem: ale został ładnie do niego przesłany.

Teraz działa;) Dziękuje Ci bardzo za pomoc a przede wszystkim cierpliwość. Pozdrawiam!:)

P.S. Prośba do Admina o wyrzucenie postu wyżej (zapomniałem sie zalogować)

0

czy mógłbyś jeszcze zerknąć na widoki w tym projekcie? Usiłuje przekazać dane z bazy ale tak jakby controller jej nie widział. Myślałem że coś źle robie z widokiem częściowym więc zrobiłem zwykły ale raczej jest problem przy samym łączeniu z bazą.
https://github.com/S..../S..Za...

1

Nie wiem co masz zepsute. Ściągnąłem projekt, w web.config zmieniłem sobie tylko nazwę serwera na mój i się pięknie połączyłem i pobrałem dane z mojego serwera.
W załącznikach masz screeny

0
ne0 napisał(a):

Nie wiem co masz zepsute. Ściągnąłem projekt, w web.config zmieniłem sobie tylko nazwę serwera na mój i się pięknie połączyłem i pobrałem dane z mojego serwera.
W załącznikach masz screeny

Czyli wynika że coś w web.configu poknociłem..

0

Hehe patrz jaki kolejny login dostałeś :P

Tak, podejrzewam że może to być problem z connectionStringiem. Jakiej bazy używasz?

0
ne0 napisał(a):

Hehe patrz jaki kolejny login dostałeś :P

Tak, podejrzewam że może to być problem z connectionStringiem. Jakiej bazy używasz?

Tak to jest jak człowiek jest raz zalogowany a raz nie;) Wracając do tematu. Jest to zwykła baza stworzona w SQL Serverze. Connection string wygląda tak:

<connectionStrings>
    <add name="EFDbContext" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=SystemZamowien;Integrated Security=True" providerName="System.Data.SqlClient"/>
  </connectionStrings>
0

A jaka wersja SQL Servera? Sadzac po connection stringu powinienes miec local SQL Server Express 2012, ale ekspertem nie jestem:)

0
FakeAccount napisał(a):

A jaka wersja SQL Servera? Sadzac po connection stringu powinienes miec local SQL Server Express 2012, ale ekspertem nie jestem:)

SQL Server 2012/ Visual Studio 2012 Proffesional

1

mój serwer nazywa się LHRT3-BRIDGE, connectionString wygląda tak:

    <add name="DefaultConnection" connectionString="Data Source=LHRT3-BRIDGE; Integrated Security=True; Initial Catalog=MojaBaza" providerName="System.Data.SqlClient" />

spróbuj u siebie wstawić nazwę serwera, bez tego (localdb)\version

0

(localdb)\v11.0 - to jest nazwa serwera. Poniżej screen jak to u mnie wygląda, może coś rozjaśni:

0

A probowales sie do tej bazy polaczyc czyms innym? Np Management Studio?

Znalazlem na stackOverflow takie cos:

Steps to connect LocalDB to Visual Studio Server Explorer

    Open command prompt
    Run SqlLocalDB.exe start v11.0
    Run SqlLocalDB.exe info v11.0
    Copy the Instance pipe name that starts with np:\...
    In Visual Studio select TOOLS > Connect to Database...
    For Server Name enter (localdb)\v11.0. If it didn't work, use the Instance pipe name that you copied earlier. You can also use this to connect with SQL Management Studio.
    Select the database on next dropdown list
    Click OK

Sprobuj z tym Instance Pipe Name

0

Nie mam Managment Studio. Próbowałem według powyższego scenariusza ale bez zmian. Baza działa i łączy ale nie da się z niej pobrać danych:(

0

Baza jest przykładowo wypełniona od samego początku, poniżej screen:

0

Ok. W końcu działa. Tylko do końca nie rozumiem istoty działania. W Server explorerze generuje się dynamicznie tabela "Products" (wcześniej sam dodawałem przez add New table), gdy ją wypełniłem - dane są pobierane bez problemu. Tworzy się również osobna tabela "__MigrationHistory". Dlaczego ta pierwsza tabela generuje się dynamicznie i z taką nazwą (wszędzie w kodzie używa zmiennej "Produkty"), i co znaczy ta druga tabela? Załączam screen

1

Używasz podejścia Code First, czyli "baza danych z kodu" . Dlatego tworzy się dodatkowa tabela __MigrationHistory w której są zbierane informacje na temat migracji bazy danych. Przeczytaj tutaj. http://msdn.microsoft.com/en-us/data/dn456841.aspx

Co do pierwszego pytania to nie do końca rozumiem co się dzieje, załączasz jednego screena na którym tabela to Produkty, a zaraz potem załączasz drugiego screena i tam już tabela nazywa się Products... coś mi tu nie gra.

0

To fakt troche zakręciłem. Generalnie chodzi o to że wcześniej tabele "Produkty" tworzyłem sobie z palca (przez add New table) tymczasem nie wiedzieć czemu automatycznie generowała się również druga tabela "Products" i to z niej dało się te dane pobierać. Dlatego wykasowałem tę pierwszą i wszystko działa. Tylko cały czas nie łapie skąd ta nazwa "Products", ponieważ wszędzie w kodzie nazywam ją "Produkty".

1

No to trzeba bylo tak od razu :) Problem wzial sie stad, ze prawdopodobnie pomieszales podejsce Code First z DB First. Polecam http://www.entityframeworktutorial.net/ - calkiem przejrzyscie wytlumaczone czym sie rozni jedno podejscie od drugiego i jak ktorego uzywac

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