Utilisation du référentiel générique et des procédures stockées

Je travaille sur une application existante qui utilise d’abord le modèle de repository générique et la firebase database EF6. J’appelle un proc stocké qui renvoie un type complexe qui n’est pas une entité existante dans mes modèles d’entité et, par conséquent, je ne suis pas sûr du type à donner.

Voici comment mon sp est appelé depuis ma couche de service

_unitOfWork.Repository() .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(); 

Est-ce que je crée une entité dans ma couche de données à mapper ou quelle est la meilleure approche pour les procédures stockées renvoyant des types complexes? Si tel est le cas, un mappage personnalisé est-il nécessaire ou s’agit-il simplement de créer la classe Entity?

Je vous remercie

Si vous avez une entité avec ces champs, vous pouvez appeler la méthode SqlQuery comme vous l’avez montré ci-dessus. Sinon, je suggère de créer une nouvelle classe pour mapper le résultat:

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

Je ne sais pas comment le modèle UnitOfWork est implémenté dans votre cas, mais je suppose que vous avez access à votre contexte. Dans votre classe UnitOfWork , vous pouvez créer une méthode générique comme celle-ci:

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

De cette façon, vous pouvez exécuter vos procédures de magasin comme je le montre ci-dessous:

 var result= _unitOfWork.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(); 

Le modèle de référentiel a pour object d’abstraire le stockage et la récupération des données afin de protéger votre code client, par exemple la couche métier (couche de service dans votre cas), de toute information sur la façon dont les données sont conservées. Les instructions SQL, par exemple, n’existeraient que dans vos classes Repository et ne se répercuteraient pas dans votre code.

Si vous exposez des noms et des parameters SQL, Procédure stockée et parameters à votre code client, vous n’obtenez pas beaucoup d’avantages avec le modèle de référentiel, et vous ne pouvez pas vraiment l’appeler un référentiel. Vous perdez l’avantage de pouvoir simuler le référentiel et de tester votre couche métier indépendamment de votre couche d’access aux données. Cela signifie que des tests d’intégration (nécessitant une instance de firebase database complète) sont nécessaires pour vérifier la logique métier.

Envisagez de refactoriser afin de disposer d’une classe CountryRepository dotée d’une méthode GetCountry (int CountryId, DateTime fromDate, DateTime toDate) qui renvoie une entité Country ou similaire. Je pense que vous conviendrez que la lisibilité de votre code sera bien améliorée par rapport au code de votre question.

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

Le code client serait alors par exemple

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

Voir aussi cette question SO

ma façon

  IQueryable customerQuery = _uow.SqlQuery(@" DECLARE @UserId INT = {0} EXEC Cm_GetCustomersByUserId @UserId", filter.UserId).AsQueryable(); IQueryable 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(); 

La manière ci-dessus ne fonctionne pas dans mon cas et j’écris ci-dessus et cela fonctionne pour moi pour n’importe qui dans mon cas

 public virtual IEnumerable GetWithRawSql(ssortingng query, params object[] parameters) { return DbSet.SqlQuery(query, parameters).ToList(); } 

Interface

 IEnumerable GetWithRawSql(ssortingng query, params object[] parameters);