work unit pattern patron framework c# entity-framework stored-procedures ddd-repositories

c# - unit - repository pattern php



Uso de repositorio genérico y procedimientos almacenados (3)

Estoy trabajando en una aplicación existente que utiliza primero el patrón Repo genérico y la base de datos EF6. Estoy llamando a un proceso almacenado que devuelve un tipo complejo que no es una entidad existente en mis modelos de entidad y, por lo tanto, no estoy seguro de qué tipo dar.

Así es como se llama a mi sp desde mi capa de servicio

_unitOfWork.Repository<Model>() .SqlQuery("sp_Get @FromDateTime, @ToDateTime, @CountyId", new SqlParameter("FromDateTime", SqlDbType.DateTime) { Value = Request.FromDateTime }, new SqlParameter("ToDateTime", SqlDbType.DateTime) { Value = Request.TripToDateTime }, new SqlParameter("CountyId", SqlDbType.Int) { Value = Convert.ToInt32(Request.County) } ).ToList();

¿Creé una Entidad en mi capa de datos para mapear o cuál es el mejor enfoque para los procedimientos almacenados que devuelven tipos complejos? Si es así, ¿se necesita una asignación personalizada o solo se trata de crear la clase Entity?

gracias


Si tiene una entidad con esos campos, puede llamar al método SqlQuery como se muestra arriba, de lo contrario, le sugiero que cree una nueva clase para asignar el resultado:

public class Result { public int CountyId { get; set; } public DateTime FromDateTime { get; set; } public DateTime ToDateTime { get; set; } }

No sé cómo se implementa el patrón UnitOfWork en su caso, pero supongo que tiene acceso a su Contexto. En tu clase UnitOfWork puedes crear un método genérico como este:

public class UnitOfWork { private YourContext Context { get; set; } public DbRawSqlQuery<T> SQLQuery<T>(string sql, params object[] parameters) { return Context.Database.SqlQuery<T>(sql, parameters); } }

De esta forma, puede ejecutar los procedimientos de su tienda como se muestra a continuación:

var result= _unitOfWork.SqlQuery<Result>("sp_Get @FromDateTime, @ToDateTime, @CountyId", new SqlParameter("FromDateTime", SqlDbType.DateTime) { Value = Request.FromDateTime }, new SqlParameter("ToDateTime", SqlDbType.DateTime) { Value = Request.TripToDateTime }, new SqlParameter("CountyId", SqlDbType.Int) { Value = Convert.ToInt32(Request.County) } ).ToList();


mi manera

IQueryable<Cm_Customer> customerQuery = _uow.SqlQuery<Cm_Customer>(@" DECLARE @UserId INT = {0} EXEC Cm_GetCustomersByUserId @UserId", filter.UserId).AsQueryable(); IQueryable<Cm_Customer> custs = customerQuery.IncludeMultiple(k => k.Cm_CustomerLocations, k => k.Cm_CustomerSalesmans, k => k.Cm_CustomerMachineparks, k => k.Cm_CustomerAuthenticators, k => k.Cm_CustomerInterviews, k => k.Cm_CustomerRequest, k => k.Cm_MachineparkRental).AsQueryable();

Por encima de la manera no funciona en mi caso y escribo arriba y esto es trabajado para mí para cualquier persona en mi caso


El objetivo del Patrón de repositorio es abstraer el almacenamiento y la recuperación de datos para proteger el código de su cliente, por ejemplo, la capa empresarial (capa de servicio en su caso) de la necesidad de saber algo sobre cómo persisten los datos. Las sentencias SQL, por ejemplo, solo existirían dentro de las clases de su Repositorio, y no se propagarían a lo largo de su código.

Si expone los nombres y parámetros de SQL Stored Procedure a su código de cliente, no obtiene mucho beneficio del Patrón de repositorio, y si realmente no puede llamarlo Repositorio. Perderá el beneficio de poder simular el repositorio y probar su capa empresarial independientemente de su capa de acceso a datos. Esto significa que se requieren pruebas de integración (que requieren una instancia completa de la base de datos) para verificar la lógica comercial.

Considere volver a factorizar para que tenga una clase CountryRepository que tenga un método GetCountry (int CountryId, DateTime fromDate, DateTime toDate) que devuelva una entidad Country o similar. Creo que estarás de acuerdo en que la legibilidad de tu código mejorará mucho en comparación con el código en tu pregunta.

public class CountryRepository { public Country GetCountry(int CountryId, DateTime fromDate, DateTime toDate) { // EF or ADO.NET code here } }

El código del cliente sería, por ejemplo,

var c = unitOfWork.CountryRepository.GetCountry(1, DateTime.Now.AddYears(-1), DateTime.Now);

Ver también esta pregunta SO