ardalis / Specification

Base class with tests for adding specifications to a DDD model

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

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.