work with unit transaction teachable programming pattern patron hamedani generic framework courses c# entity-framework repository ninject sharp-repository

c# - with - patron unit of work



Cómo inyectar Entity Framework DbContext en el ConfigurationBasedRepository de SharpRepository (2)

Realmente me gustaría usar SharpRepository junto con Ninject , pero no entiendo cómo configurar Ninject para compartir el Entity Framework DbContext entre los repositorios.

Estoy usando Entity Framework versión 5 y Ninject versión 3.

Actualmente estoy usando Ef5Repository en mi código fuente, pero quiero reemplazarlo con ConfigurationBasedRepository . Pero no puedo averiguar cómo pasar (o inyectar) EF DbContext a los repositorios.

Ejemplo (estado actual):

using SharpRepository.Repository; public interface IProductRepository : IRepository<Product> { } using SharpRepository.Ef5Repository; using System.Data.Entity; // TODO Tightly coupled to Ef5Repository. public class ProductRepository : Ef5Repository<Product>, IProductRepository { // TODO The DbContext has to be injected manually. public ProductRepository(DbContext context) : base(context) { } // [...] }

Gol:

using SharpRepository.Repository; public interface IProductRepository : IRepository<Product> { } public class ProductRepository : ConfigurationBasedRepository<Product, int>, IProductRepository { // [...] }

Ya he leído las dos publicaciones del blog SharpRepository: Getting Started y SharpRepository: Configuration , pero ambas no me ayudan, ya que:

  1. El DIC utilizado es StructureMap, no Ninject.
  2. Los ejemplos del código fuente están incompletos (por ejemplo, el uso de variables no declaradas).

Entonces, mi pregunta: ¿Puede alguien proporcionarme algún ejemplo de código fuente para lograr el objetivo descrito anteriormente (compartir una instancia de Entity Framework DbContext entre todos los repositorios que extienden ConfigurationBasedRepository )?


En primer lugar, ¡la solución provista en la respuesta de Jeff T funciona!

Concluiré los pasos que tomé para hacer que Ninject funcione en un proyecto ASP.NET MVC 4 + EF 5. Es importante mencionar que el patrón del Repositorio específico se implementa a través de SharpRepository en el siguiente ejemplo.

Software requerido

  1. Instale Ninject y "Ninject.MVC3" (que también instala "Ninject.Web.Common") a través de NuGet .
  2. Instale SharpRepository , "SharpRepository para EF5" y "SharpRepository con Ninject IOC" a través de NuGet .

Definir la capa de repositorio.

  1. Cree una clase derivada de DbContext , por ejemplo, Domain.EfContext . Es el

    msgstr "forma recomendada de trabajar con contexto".

    • Declare todos los DbSet<T> requeridos como propiedades públicas, por ejemplo, productos public DbSet<Product> Products { get; set; } public DbSet<Product> Products { get; set; }
    • Declare los siguientes dos constructores en la clase Domain.EfContext :

      public EfContext() : base() {} public EfContext(string connectionName) : base(connectionName) {}

  2. Defina una interfaz para el repositorio específico , por ejemplo:

    // TODO By extending IRepository, the interface implements default Create-Read-Update-Delete (CRUD) logic. // We can use "traits" to make the repository more "specific", e.g. via extending "ICanInsert". // https://github.com/SharpRepository/SharpRepository/blob/master/SharpRepository.Samples/HowToUseTraits.cs public interface IProjectRepository : IRepository<Project> { // TODO Add domain specific logic here. }

  3. Defina una clase que implemente el Repositorio específico y herede de SharpRepository.Repository.ConfigurationBasedRepository<T, TKey> , por ejemplo:

    public class ProductRepository : ConfigurationBasedRepository<Product, int>, IProductRepository { // TODO Implement domain specific logic here. }

Definir la capa de consumidor.

  1. Crear un controlador, por ejemplo, Controllers.ProductController .

    public class ProductController : Controller { private IProductRepository Repository { get; private set; } // TODO Will be used by the DiC. public ProductController(IProductRepository repository) { this.Repository = repository; } }

Configure la inyección de dependencia (DI) a través del Ninject del contenedor de inyección de dependencia (DiC)

El archivo App_Start/NinjectWebCommon.cs es creado automáticamente por Ninject.Web.Common y podemos cargar nuestros módulos y registrar nuestros servicios en el método RegisterServices(IKernel kernel) : void de la clase NinjectWebCommon . Aquí está el código fuente completo de ese método para el ejemplo:

private static void RegisterServices(IKernel kernel) { kernel.BindSharpRepository(); RepositoryDependencyResolver.SetDependencyResolver( new NinjectDependencyResolver(kernel) ); string connectionString = ConfigurationManager.ConnectionStrings["EfContext"].ConnectionString; kernel.Bind<DbContext>() .To<EfContext>() .InRequestScope() .WithConstructorArgument("connectionString", connectionString); kernel.Bind<IProductRepository>().To<ProductRepository>(); }

Defina la siguiente sección de sharpRepository en Web.config :

<sharpRepository> <repositories default="ef5Repository"> <repository name="ef5Repository" connectionString="EfContext" cachingStrategy="standardCachingStrategy" dbContextType="Domain.EfContext, Domain" factory="SharpRepository.Ef5Repository.Ef5ConfigRepositoryFactory, SharpRepository.Ef5Repository" /> </repositories> </sharpRepository>

Además, la sección connectionStrings para completar el ejemplo (estoy usando SQL Server LocalDB).

<connectionStrings> <add name="EfContext" providerName="System.Data.SqlClient" connectionString="Data Source=(localdb)/v11.0;Initial Catalog=Domain;Integrated Security=True" /> </connectionStrings>

Espero que esta conclusión ayude a otras personas a poner en funcionamiento ASP.NET MVC 4 junto con Entity Framework 5 y SharpRepository.

Por favor, déjeme una respuesta si hice uno o más pasos innecesarios o si ve posibilidades de mejorar la arquitectura descrita en el ejemplo.

Por cierto, tuve que agregar el atributo dbContextType a la sección del repository para que funcione (en contraste con la respuesta de Jeff T).

EDITAR (2013-08-28): Tachó pasos innecesarios (no es necesario con la última versión de SharpRepository).


Primero, deberá instalar el paquete SharpRepository.Ioc.Ninject NuGet . Aquí hay métodos de extensión para conectar Ninject para manejar la carga de un repositorio genérico y configurar la resolución de dependencias que utiliza SharpRepository.

Siempre que esté configurando sus reglas de enlace de Ninject (todas las llamadas a kernel.Bind <>), deberá agregar:

kernel.BindSharpRepository();

A continuación, en su código Global.asax, App_Start o en su lógica Bootstrapper (donde quiera que esté llamando el código de inicio de la aplicación) deberá agregar lo siguiente:

// kernel is the specific kernel that you are setting up all the binding for RepositoryDependencyResolver.SetDependencyResolver(new NinjectDependencyResolver(kernel));

Esto le dirá a SharpRepository que use este Ninject Kernel cuando obtenga un nuevo DbContext.

Lo último que debe hacer es configurar las reglas de enlace para el propio DbContext. Si está en una aplicación web, lo más probable es que desee que el alcance de DbContext sea por solicitud. Personalmente no uso Ninject pero encontré esta referencia para usar InRequestScope . Creo que tu código se vería así:

kernel.Bind<DbContext>().To<MyCustomEfContext>().InRequestScope().WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["MyCustomEfContext"].ConnectionString);

La mayoría de las personas no necesitarán la siguiente pieza, pero si tiene lógica personalizada en su CustomEfContext (tengo un reemplazo para el inicio de sesión en las llamadas a SaveChanges () por ejemplo), entonces deberá definir su tipo de contexto personalizado en el archivo de configuración. al igual que:

<repositories> <repository name="ef5Repository" connectionString="CustomEfContext" cachingStrategy="standardCachingStrategy" dbContextType="My.Data.CustomEfContext, My.Data" factory="SharpRepository.Ef5Repository.Ef5ConfigRepositoryFactory, SharpRepository.Ef5Repository" /> </repositories>

Donde dbContextType define el tipo de DbContext personalizado que está utilizando con el tipo completo, sintaxis de espacio de nombres. Si haces esto, entonces necesitarás establecer Ninject en Bind en el contexto personalizado cambiando .Bind <DbContext> () a .Bind <CustomEfContext> (). Pero como he dicho normalmente, puedes usar DbContext directamente sin ningún problema.