How can I successfully ingerit from IRepository and use it?

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
11 years ago
Hi,
I would like to create a new IRepository implementation because I need a special handling for an entity: I would like to load it from different tables into just one model.

To do that, I created the type Nop.Core.Data.Catalog.ProductVariantRepository, which inherits from  Nop.Core.Data.IRepository.

After that, I went to Nop.Web.Framework.DependencyRegistrar and added the following row

            builder.RegisterType<ProductVariantRepository>().As(typeof(IRepository<>)).InstancePerHttpRequest();

just before this one:
            
            builder.RegisterGeneric(typeof(EfRepository<>)).As(typeof(IRepository<>)).InstancePerHttpRequest();

When I try to open my store, I get this error message:
The type 'Nop.Core.Data.Catalog.ProductVariantRepository' is not assignable to service 'Nop.Core.Data.IRepository`1'.

Stack Trace:


[ArgumentException: The type 'Nop.Core.Data.Catalog.ProductVariantRepository' is not assignable to service 'Nop.Core.Data.IRepository`1'.]
   Autofac.Builder.RegistrationBuilder.CreateRegistration(Guid id, RegistrationData data, IInstanceActivator activator, IEnumerable`1 services, IComponentRegistration target) +652
   Autofac.Builder.RegistrationBuilder.CreateRegistration(IRegistrationBuilder`3 rb) +972
   Autofac.Builder.RegistrationBuilder.RegisterSingleComponent(IComponentRegistry cr, IRegistrationBuilder`3 rb) +152
   Autofac.<>c__DisplayClassa`1.<RegisterType>b__9(IComponentRegistry cr) +146
   Autofac.ContainerBuilder.Build(IComponentRegistry componentRegistry, Boolean excludeDefaultModules) +383
   Autofac.ContainerBuilder.Update(IComponentRegistry componentRegistry) +132
   Autofac.ContainerBuilder.Update(IContainer container) +181
   Nop.Core.Infrastructure.DependencyManagement.ContainerManager.UpdateContainer(Action`1 action) in D:\nopcommerce\Libraries\Nop.Core\Infrastructure\DependencyManagement\ContainerManager.cs:161
   Nop.Core.Infrastructure.DependencyManagement.ContainerConfigurer.Configure(IEngine engine, ContainerManager containerManager, EventBroker broker, NopConfig configuration) in D:\nopcommerce\Libraries\Nop.Core\Infrastructure\DependencyManagement\ContainerConfigurer.cs:36
   Nop.Core.Infrastructure.NopEngine.InitializeContainer(ContainerConfigurer configurer, EventBroker broker, NopConfig config) in D:\nopcommerce\Libraries\Nop.Core\Infrastructure\NopEngine.cs:58
   Nop.Core.Infrastructure.NopEngine..ctor(EventBroker broker, ContainerConfigurer configurer) in D:\nopcommerce\Libraries\Nop.Core\Infrastructure\NopEngine.cs:33
   Nop.Core.Infrastructure.NopEngine..ctor() in D:\nopcommerce\Libraries\Nop.Core\Infrastructure\NopEngine.cs:25
   Nop.Core.Infrastructure.EngineContext.CreateEngineInstance(NopConfig config) in D:\nopcommerce\Libraries\Nop.Core\Infrastructure\EngineContext.cs:55
   Nop.Core.Infrastructure.EngineContext.Initialize(Boolean forceRecreate) in D:\nopcommerce\Libraries\Nop.Core\Infrastructure\EngineContext.cs:24
   Nop.Web.MvcApplication.Application_Start() in D:\nopcommerce\Presentation\Nop.Web\Global.asax.cs:56

[HttpException (0x80004005): The type 'Nop.Core.Data.Catalog.ProductVariantRepository' is not assignable to service 'Nop.Core.Data.IRepository`1'.]
   System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext context, HttpApplication app) +587
   System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +194
   System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +352
   System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +405
   System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +368

[HttpException (0x80004005): The type 'Nop.Core.Data.Catalog.ProductVariantRepository' is not assignable to service 'Nop.Core.Data.IRepository`1'.]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +646
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +141
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +771


Am I doing something wrong?
How could I do that?
I need to load product variant with more infos than it is already modeled, and I separated these due to performance issues.

Thanks,
Oscar
11 years ago
Hey Guys,
Just found the error out:

builder.RegisterType<ProductVariantRepository>().As(typeof(IRepository<ProductVariant>)).InstancePerHttpRequest();

Adding the "<ProductVariant>" to the line solves the issue :)
11 years ago
you don't need to make changes to Nop.Web.Framework.DependencyRegistrar, everything needed to use tables as IRepository is already done

Just define a private variable


private readonly IRepository<ProductVariant> _productVariantRepository;


and either inject into the constructor

IRepository<ProductVariant> productVariantRepository
_productVariantRepository = productVariantRepository


or resolve it, something like


_productVariantRepository = EngineContext.Current.Resolve< IRepository< ProductVariant > >() ;
11 years ago
keesjan wrote:
you don't need to make changes to Nop.Web.Framework.DependencyRegistrar, everything needed to use tables as IRepository is already done

Just define a private variable


private readonly IRepository<ProductVariant> _productVariantRepository;


and either inject into the constructor

IRepository<ProductVariant> productVariantRepository
_productVariantRepository = productVariantRepository


or resolve it, something like


_productVariantRepository = EngineContext.Current.Resolve< IRepository< ProductVariant > >() ;


Hi,
thanks for your answer!
As far as I understood, this would enable me to retrieve and insert product variant info in the database in the default way (just adding rows to a table). Is this correct?

In my case, I have a "reputation" information that I would like to add to the product variant info (it is not in the product variant table due to performance purposes). So I would like to have a custom retrieval operation, where I would perform a join between the product variant table and the reputation table.
Your solution would not provide me this ability, since the IRepository is the defaujlt one (EfRepository).
For this reason I would like to create my own and, if I got it right, I have to register it. Is that correct?

Thanks!
11 years ago
not sure I understand you 100% but IRepository exposes the underlying table as IQueryable<T>

IQueryable<T> Table { get; }

This allow you to do joins among others, something like

var query = from pv in _productVariantRepository.Table
                  join r in _reputationRepository.Table on pv.ProductVariantId equals r.ProductVariantId
11 years ago
Hi,
I'm sorry if I am not clear enough,l let me try to makes things better:

I have the ProductVariant table and a Reputation table. The reputation information has a complex calculation and because of that was not included in the ProductVariant table.

BUT, anytime I load a ProductVariant, I need to have the reputation information associated.

I could use the queryable interface to make this join, but doing that would force me to change all the methods that already load a productVariant in order to make this join.

An alternative solution is: create a custom IRepository that already makes this join, so anyone calling it will receive the productVariant with the reputation information already populated. This is the alternative I chose, this way all implemented methods will already make use of the custom retrieval.

Is it clear? What do you think about this alternative?
:)
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.