2015-01-15 15 views
8

Sto lavorando a un'applicazione esistente, utilizza prima il modello Repo generico e il database EF6. Sto chiamando un proc memorizzato che restituisce un tipo complesso che non è un'entità esistente nei miei modelli di entità e quindi non sono sicuro di quale tipo dare.Utilizzo di repository generico e stored procedure

Ecco come il mio sp viene chiamato dal mio livello di servizio

_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(); 

faccio a creare un entità nel mio livello di dati da mappare o che cosa è l'approccio migliore per le stored procedure che tornano tipi complessi. Se è così c'è mappatura personalizzata necessaria o è solo un caso di creare la classe Entity

si

risposta

11

ringrazio Se si dispone di un ente con quei campi è possibile chiamare il metodo sqlquery come si mostra in precedenza, se non, allora vi consiglio di creare una nuova classe per mappare il risultato:

public class Result 
{ 
    public int CountyId { get; set; } 

    public DateTime FromDateTime { get; set; } 

    public DateTime ToDateTime { get; set; } 
} 

io non so come è implementato il modello UnitOfWork nel tuo caso, ma suppongo che si ha accesso al vostro contesto. Nella classe UnitOfWork si potrebbe creare un metodo generico come questo:

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); 
    } 
} 

In questo modo, è possibile eseguire le procedure di negozio come mostro qui di seguito:

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(); 
+0

Questo approccio ha funzionato per me. Ho dovuto aggiungere anche la mia nuova classe/entità alla mia classe di contesto. 'public DbSet modelName {get; impostato; } 'e dovevo assicurarmi che la mia nuova entità avesse una' [chiave] 'ed ereditata da' EntityBase' – user2329438

7

Lo scopo del Repository Pattern è quello di astrarre lo storage & recupero di dati per proteggere il codice cliente ad es. livello aziendale (livello di servizio nel tuo caso) dal bisogno di sapere qualcosa su come i dati vengono mantenuti. Le istruzioni SQL, ad esempio, esisterebbero solo all'interno delle classi del repository e non si propagheranno su tutto il codice.

Se si espongono SQL, i nomi e i parametri della stored procedure sul codice client, non si ottiene molto vantaggio dal modello del repository e, in effetti, non è possibile chiamarlo affatto repository. Si perde il vantaggio di essere in grado di prendere in giro il repository e testare il livello aziendale indipendentemente dal livello di accesso ai dati. Ciò significa che i test di integrazione (che richiedono un'istanza completa del database) sono necessari per verificare la logica aziendale.

Considerare il ri-factoring in modo da avere una classe CountryRepository che ha un metodo GetCountry (int CountryId, DateTime fromDate, DateTime toDate) che restituisce un'entità Paese o simile. Penso che concorderai che la leggibilità del tuo codice sarà molto migliorata rispetto al codice della tua domanda.

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

Codice cliente sarebbe quindi ad es.

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

Vedi anche questo SO question

0

mio modo

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(); 

Sopra modo non funziona nel mio caso e scrivo sopra e questo è lavorato per me per chiunque nel mio caso

0
public virtual IEnumerable<T> GetWithRawSql(string query, params object[] parameters) 
     { 
      return DbSet.SqlQuery(query, parameters).ToList(); 
     } 

Interfaccia

IEnumerable<T> GetWithRawSql(string query, params object[] parameters);