Asp core, Object reference not set to an instance of an object in Repository pattern

10,770

You are using static methods and the constructor is never called as you never create the object. You would have to change your constructor to:

public static AuthorReposetory()
{
    _context = new ApplicationDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("DefualtConnection")));
}

but that's quite bad practice since you have to setup the connection in the constructor and this also created a hard dependency on your context class.

A better solution would be to create a non static class

public class AuthorRepository : IAuthorRepository
{
    private ApplicationDbContext _context;

    public AuthorRepository(ApplicationDbContext context)
    {
        _context = context;
    }

    // ...
}

public interface IAuthorRepository
{
    // ...
}

Reverse the dependency with injection:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    //define Connection string and setup dependency injection
    services.AddDbContext<ApplicationDbContext>(option => option.UseSqlServer(Configuration.GetConnectionString("DefualtConnection")));
    services.AddScoped<IAuthorRepository, AuthorRepository>();
    // ...
}

Controller:

public HomeController
{
    private IAuthorRepository _authorRepository;

    public HomeController(IAuthorRepository authorRepository)
    {
        _authorRepository = authorRepository;
    }

    [HttpGet]
    public IActionResult Index()
    {
        var q = _autorRepository.GetAuthorList();
        return View(q);
    }
}
Share:
10,770

Related videos on Youtube

topcool
Author by

topcool

Updated on June 04, 2022

Comments

  • topcool
    topcool almost 2 years

    I am working on an asp core 1.1 and i want to create a select repository pattern in my project.

    my code in repository class :

    public class AuthorReposetory : IDisposable
    {
        private static ApplicationDbContext _context;
    
        public AuthorReposetory(ApplicationDbContext context)
        {
            _context = context;
        }
    
    
    
    
        public static List<Author> GetAuthorList()
        {
            List<Author> model = new List<Author>();
    
            model = _context.authors.Select(a => new Author
            {
                AuthorId = a.AuthorId,
                AuthorName = a.AuthorName,
                AuthorDescription = a.AuthorDescription
            }).ToList();
    
            return model;
        }
    
        public void Dispose()
        {
            throw new NotImplementedException();
        }
    
        ~AuthorReposetory()
        {
            Dispose();
        }
    }
    

    and in controller

    [HttpGet]
    public IActionResult Index()
    {
        var q = AuthorReposetory.GetAuthorList();
        return View(q);
    }
    

    Update

    Here is my StartUp Class

    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();
        }
    
        public IConfigurationRoot Configuration { get; }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //define Connection string
            services.AddDbContext<ApplicationDbContext>(option => option.UseSqlServer(Configuration.GetConnectionString("DefualtConnection")));
            //For Create and use identity in database
            services.AddIdentity<ApplicationUser, ApplicationRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();
    
    
            // Add framework services.
            services.AddMvc();
            services.AddAutoMapper();
            services.AddPaging();
        }
    
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();
    
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }
    
            app.UseStaticFiles();
            app.UseIdentity();
    
    
            app.UseMvc(routes =>
            {
    
                //New Area For Admin
                routes.MapRoute(
                    name: "Admin",
                    template: "{area:exists}/{controller=Admin}/{action=Index}/{id?}");
    
                //New Area For User
                routes.MapRoute(
                    name: "UserProfile",
                    template: "{area:exists}/{controller=UserProfile}/{action=Index}/{id?}");
    
                //tranditional Routing
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
    

    My Connection string in appsettings.json

    {
      "ConnectionStrings": {
      "DefualtConnection" : "Data Source=.;Initial Catalog=DataBaseName;User ID = sa; Password = 123"
      },
    
    
    
    
    
      "Logging": {
       "IncludeScopes": false,
        "LogLevel": {
         "Default": "Warning"
        }
      }
    }
    

    The problem is Object reference not set to an instance of an object when run model = _context.authors.Select(a => new Author in repository. In the above i show controller code, Repository class code and start up code to figure out. Where can the problem be?

    Note : everything is good in controller. just problem is in repository class.

    • Ehsan Sajjad
      Ehsan Sajjad about 6 years
      show your starup class where you configure context
    • topcool
      topcool about 6 years
      @Ehsan Sajjad I add it to my question
    • Ehsan Sajjad
      Ehsan Sajjad about 6 years
      might be the connection string is not correct, as you have DBContext configure in the startup
    • topcool
      topcool about 6 years
      @EhsanSajjad Do I need to put code of the connection?
    • Brad
      Brad about 6 years
      Why is your _context static in AuthorRepository?
  • topcool
    topcool about 6 years
    @hix my context works without repository and in controller but when i use it in repository class not works, any idea to solve it?
  • Hix
    Hix about 6 years
    Well, I can not see any controller or repository in your configuration. Include them, and your solution will work ;) I think that the exception occurs when you make a call to your AuthorReposetory class from your controller.
  • Hix
    Hix about 6 years
    And please do not put an exception in the dispose method. It is like you shoot yourself in the head :)
  • topcool
    topcool about 6 years
    I don`t know what I have to do exactly ?
  • Hix
    Hix about 6 years
    You have to add your repo, and service classes into dependency injection. You can do that in the ConfigureServices method in your startup class. The syntax is like : services.AddTransient<TMyInterface>(TMyInterfaceImplementati‌​on);
  • Ehsan Sajjad
    Ehsan Sajjad about 6 years
    @saeed put break point in repository constructor and check if context is being set
  • Hix
    Hix about 6 years
    It won't call your constructor. It is not aware of its existence. You have to tell the engine what I have mentioned above.
  • topcool
    topcool about 6 years
    @Hix in which class shoud i change?
  • Hix
    Hix about 6 years
    I told you already: You have to add your repo, and service classes into dependency injection. You can do that in the ConfigureServices method in your startup class. The syntax is like : services.AddTransient<TMyInterface, TMyInterfaceImplementation>();
  • Ehsan Sajjad
    Ehsan Sajjad about 6 years
    you need to register your repository class in container
  • topcool
    topcool about 6 years
    I add it to ConfigureServcies but Repository constructor not work again
  • Ehsan Sajjad
    Ehsan Sajjad about 6 years
    this should work i think, may be you have something else missing too
  • topcool
    topcool about 6 years
    maybe i sholud create a new instance of repository in controller to use it
  • Brad
    Brad about 6 years
    services.AddDbContext() registers the DbContext in DI. There's no need to do it again. And it's best to add the repositories as Scoped, not Transient.
  • Mike
    Mike about 6 years
    @Brad true that. Edited.