fullstackhero / dotnet-starter-kit

Production Grade Cloud-Ready .NET 8 Starter Kit (Web API + Blazor Client) with Multitenancy Support, and Clean/Modular Architecture that saves roughly 200+ Development Hours! All Batteries Included.

Home Page:https://fullstackhero.net/dotnet-webapi-boilerplate/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Repository can be injected but when call any method, get object reference error

mustafaulukaya opened this issue · comments

Hi,

I use ardalis spesifications with entity framework. I wrote my app in .net 7 and i use onion architecture with mediatr pattern. I have a generic interface named "IRepository" and i define it scoped. When i inject this variable is not null but when i use any method of repository then i got an error "Object reference set not an instance of an object"

Codes

using Ardalis.Specification;
using Domain.Common.Contracts;

namespace Application.Common.Persistence
{
    // The Repository for the Application Db
    // I(Read)RepositoryBase<T> is from Ardalis.Specification

    /// <summary>
    /// The regular read/write repository for an aggregate root.
    /// </summary>
    public interface IRepository<T> : IRepositoryBase<T>
        where T : class, IAggregateRoot
    {
    }

    /// <summary>
    /// The read-only repository for an aggregate root.
    /// </summary>
    public interface IReadRepository<T> : IReadRepositoryBase<T>
        where T : class, IAggregateRoot
    {
    }

    /// <summary>
    /// A special (read/write) repository for an aggregate root,
    /// that also adds EntityCreated, EntityUpdated or EntityDeleted
    /// events to the DomainEvents of the entities before adding,
    /// updating or deleting them.
    /// </summary>
    public interface IRepositoryWithEvents<T> : IRepositoryBase<T>
        where T : class, IAggregateRoot
    {
    }
}
services.AddScoped(typeof(IRepository<>), typeof(ApplicationDbRepository<>));
using Application.Common.Persistence;
using Ardalis.Specification;
using Ardalis.Specification.EntityFrameworkCore;
using Domain.Common.Contracts;
using Infrastructure.Persistance.Context;
using Mapster;

namespace Infrastructure.Persistance.Repository
{
    // Inherited from Ardalis.Specification's RepositoryBase<T>
    public class ApplicationDbRepository<T> : RepositoryBase<T>, IReadRepository<T>, IRepository<T>
        where T : class, IAggregateRoot
    {
        public ApplicationDbRepository(ApplicationDbContext dbContext)
            : base(dbContext)
        {
        }

        // We override the default behavior when mapping to a dto.
        // We're using Mapster's ProjectToType here to immediately map the result from the database.
        // This is only done when no Selector is defined, so regular specifications with a selector also still work.
        protected override IQueryable<TResult> ApplySpecification<TResult>(ISpecification<T, TResult> specification) =>
            specification.Selector is not null
                ? base.ApplySpecification(specification)
                : ApplySpecification(specification, false)
                    .ProjectToType<TResult>();
    }
}

At this point, when call

await repository.ListAsync(spec, cancellationToken);

I got object reference error.

using Application.Common.Interfaces;
using Ardalis.Specification;

namespace Application.Common.Models
{
    public static class PaginationResponseExtensions
    {
        public static async Task<PaginationResponse<TDestination>> PaginatedListAsync<T, TDestination>(
            this IReadRepositoryBase<T> repository, ISpecification<T, TDestination> spec, int pageNumber, int pageSize, CancellationToken cancellationToken = default)
            where T : class
            where TDestination : class, IDto
        {
            var list = await repository.ListAsync(spec, cancellationToken);
            int count = await repository.CountAsync(spec, cancellationToken);

            return new PaginationResponse<TDestination>(list, count, pageNumber, pageSize);
        }
    }
}
using Application.Common.Models;
using MediatR;
using Application.Common.Persistence;
using Application.Configuration.DomainParameter.Specs;

namespace Application.Configuration.DomainParameter.Features
{
    public class GetAllDomainParametersRequest : PaginationFilter, IRequest<PaginationResponse<DomainParameterDto>>
    {
    }

    public class GetAllDomainParametersRequestHandler : IRequestHandler<GetAllDomainParametersRequest, PaginationResponse<DomainParameterDto>>
    {
        private readonly IReadRepository<Domain.Entity.Configuration.DomainParameter> _repository;
        public GetAllDomainParametersRequestHandler(IReadRepository<Domain.Entity.Configuration.DomainParameter> repository) => _repository = repository;

        public async Task<PaginationResponse<DomainParameterDto>> Handle(GetAllDomainParametersRequest request,
            CancellationToken cancellationToken)
        {
            var spec = new DomainParameterBySearchSpec(request);
            return await _repository.PaginatedListAsync(spec, request.PageNumber, request.PageSize, cancellationToken);
        }
    }
}

Stack traces

image

Message:

Object reference not set to an instance of an object.
  Name Value Type
  SerializationStackTraceString " at lambda_method326(Closure, QueryContext)" string

image

SerializationStackTraceString:

   at lambda_method326(Closure, QueryContext)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

StackTrace:

   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator() in /_/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConfiguredCancelableAsyncEnumerable.cs:line 42
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.<ToListAsync>d__65`1.MoveNext()

Provider and version information

EF Core version: 7.0.7
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 7.0
Operating system: Windows 11 64 bit
IDE: Visual Studio 2022 17.6.0

Note: I tested initial project and change nothing and still got this error. I created project with this command:

fsh api new FSH.Starter

and only change database.json and hangfire.json files to locate my mssql server. When i try search brands, i got this error.

Sorry for bothering you, I didn't pass tenant so if table multitenant and you did not pass tenantId to application, then this error raised. Problem solved when tenantId passed.

commented

What did you do to solve this?
Can you give an example?