Base solution for your next web application
Open Closed

Repository Container -- Dependency Injection Error #1246


User avatar
0
arslanali created

How can i build a repository container so that i dont have to inject each and every custom repository using constructor injections in controller or application service layers. following is my plan:

public interface ISupplierRepository 
    {
        ISupplierProfileRepository _supplierProfileRepository { get; }
        ISupplierBusnsServicesRepository _supplierBusnsServiceRepository { get; }
        ISupplierBusnsCoverageRepository _supplierBusnsCoverageRepository { get; }
        ISupplierPhotosRepository _supplierPhotosRepository { get; }
        ISupplierVideosRepository _supplierVideosRepository { get; }
        ISupplierLeadsRepository _supplierLeadsRepository { get; }
        ISupplierCertificationsRepository _supplierCertificationsRpository { get; }

    }

but currently i am getting an unsatisfied dependency injection error on ISupplierRepository as i havnt implemented this interface using RepositoryBase. because RepositoryBase can only implement using a specific domain type.


5 Answer(s)
  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    You can not inject it since you did not register it. Change your interface definition to implement ITransientDependency:

    public interface ISupplierRepository : ITransientDependency
    

    See docs: <a class="postlink" href="http://www.aspnetboilerplate.com/Pages/Documents/Dependency-Injection#DocHelperInterfaces">http://www.aspnetboilerplate.com/Pages/ ... Interfaces</a>

  • User Avatar
    0
    arslanali created

    sorry but its not happening help me, review my code please: Definition:

    public interface ISupplierRepositoriesContainer: ITransientDependency
        {
            ISupplierProfileRepository _supplierProfileRepository { get; }
            ISupplierBusnsServicesRepository _supplierBusnsServicesRepository { get; }
            ISupplierBusnsCoverageRepository _supplierBusnsCoverageRepository { get; }
            ISupplierPhotosRepository _supplierPhotosRepository { get; }
            ISupplierVideosRepository _supplierVideosRepository { get; }
            ISupplierCertificationsRepository _supplierCertificationRepository { get;}
            ISupplierLeadsRepository _supplierLeadsRepository { get; }
        }
    

    Implementation:

    class SupplierRepositoryContainer: ISupplierRepositoriesContainer, ITransientDependency
        {
            public ISupplierProfileRepository _supplierProfileRepository { get; }
            public ISupplierBusnsServicesRepository _supplierBusnsServicesRepository { get; }
            public ISupplierBusnsCoverageRepository _supplierBusnsCoverageRepository { get; }
            public ISupplierPhotosRepository _supplierPhotosRepository { get; }
            public ISupplierVideosRepository _supplierVideosRepository { get; }
            public ISupplierCertificationsRepository _supplierCertificationRepository { get; }
            public ISupplierLeadsRepository _supplierLeadsRepository { get; }
    
        }
    
  • User Avatar
    0
    hikalkan created
    Support Team

    Rename SupplierRepositoryContainer class to SupplierRepositoriesContainer since naming is important for conventional dependency injection.

    There are also other problems with your code:

    1. I haven't seen that you injected dependencies into SupplierRepositoriesContainer class. If you want to use property injection, add setters to the properties (currently they are get only). Otherwise, use constructor injection to set them.

    2. I suggest you to use PascalCase for property names. This is a better practice.

  • User Avatar
    0
    arslanali created

    Hi Hikalkan, well thanks for the previous replies as they really helped me managing my repositories and application services while keeping my code neat and clean. rite now i have another small issue, may be i am making a very basic mistake.

    I have a repository container same as mentioned earlier.

    Since my core classes are all relational, which means they have navigation objects of parent and navigation list of child in them. I am using Angular SPA which requires JSON objects and they cannot be circular referenced so to handle this i have made DTOs of all these Core classes but without the navigation objects which actually worked fine.

    But now i have a complex scenario where i want to send a Complex DTO of a BusinessServices (table in db) with its Questions (Child Table) and Questions with its choices(Child of child). all of these tables are 1 to many in relationship. So i have made the DTOs as follows:

    [MapTo]
    [AutoMap(typeof(BusinessServices))]
    public class AdminServiceCompleteDto : EntityDto, IDoubleWayDto
    {
    ...... // Dto properties same as Core 
    public ICollection<AdminQuestionsDto> questions {get;set;}
    }
    [AutoMap(typeof(Qualification))]
    public class AdminQualificationDto: EntityDto,IDoubleWayDto
    {
    .....// Dto properties same as Core
    public int ServiceId {get;set;}
    public ICollection<AdminInputChoiceDto> mcqAnswers { get; set; } 
    }
    [AutoMap(typeof(CustomerInputChoice))]
    public class AdminInputChoiceDto: EntityDto,IDoubleWayDto
    {
    .....// Dto properties same as Core
    public int QuestionId {get;set;}
    }
    

    Now I send the AdminServiceCompleteDto object to Angular SPA which recieves it well and displays everything nicely.

    But when i send the updated object back and try to update the same object then nothings gets updated. I tried following but nothing works:

    Try1:

    public AdminServiceCompleteDto SetServiceData(AdminServiceCompleteDto input)
            {
               
                var service = _adminBusinessServiceRepository.Get(input.Id);
                service = input.MapTo<BusinessServices>();
                return service.MapTo<AdminServiceCompleteDto>();
            }
    // Result: Nothing gets updated.
    

    Try 2:

    public AdminServiceCompleteDto SetServiceData(AdminServiceCompleteDto input)
            {
                var service = _adminBusinessServiceRepository.InsertOrUpdate(input.MapTo<BusinessServices>());
                return service.MapTo<AdminServiceCompleteDto>();
            }
    // Result: Nothing gets updated.
    

    Try 3:

    public AdminServiceCompleteDto SetServiceData(AdminServiceCompleteDto input)
            {
                BusinessServices service = new BusinessServices();
                if (input.Id > 0)
                {
                    service = _adminDataRepositories._businessServicesRepository.Get(input.Id);
                    service = input.MapTo<BusinessServices>();
                    CurrentUnitOfWork.SaveChanges();
    
                    var qualifications = input.qualification.MapTo<List<Qualification>>();
                    foreach (var q in input.qualification)
                    {
                        q.bServId = service.Id;
                        var question = _adminDataRepositories._qualificationRepository.InsertOrUpdate(q.MapTo<Qualification>()); // program break here
                         foreach (var a in q.mcqAnswers)
                        {
                            a.qualificationId = question.Id;
                            _adminDataRepositories._customerInputChoiceRepository.InsertOrUpdate(a.MapTo<CustomerInputChoice>());
                        }
                    }
    
                }
                else
                    service =_adminDataRepositories._businessServicesRepository.Insert(input.MapTo<BusinessServices>());
    
                return service.MapTo<AdminServiceCompleteDto>();
            }
    // This gives runtime error but with no data.
    

    But it works if i bring earch DTO serperately and save them individually. Which is lengthy and cumbersome :( i would appreciate if you could give me a quick and easy process for the above problem. Arslan.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Unfortunately Entity Framework works this way by default. You have to save each entity seperately. But you can use GraphDiff in order to make save all entities at once.

    You can find more info and examples in this issue <a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate/issues/1073">https://github.com/aspnetboilerplate/as ... ssues/1073</a>.