2016-03-29 22 views
11

Se ho il seguente contesto:Come accedere a un metodo nel contesto attraverso l'unità di lavoro?

public partial class HRMainDataCTX : DbContext 
{ 
    public HRMainDataCTX() 
     : base("name=HRMainDataCTX") 
    { 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     throw new UnintentionalCodeFirstException(); 
    } 

    //DbSets 
    public virtual int SEARCHEMPLOYEE(Nullable<decimal> p_EMP_NUM, string p_EMP_NAME) 
    { 
     var p_EMP_NUMParameter = p_EMP_NUM.HasValue ? 
      new ObjectParameter("P_EMP_NUM", p_EMP_NUM) : 
      new ObjectParameter("P_EMP_NUM", typeof(decimal)); 

     var p_EMP_NAMEParameter = p_EMP_NAME != null ? 
      new ObjectParameter("P_EMP_NAME", p_EMP_NAME) : 
      new ObjectParameter("P_EMP_NAME", typeof(string)); 

     return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("SEARCHEMPLOYEE", p_EMP_NUMParameter, p_EMP_NAMEParameter); 
    } 
} 

Ora implemento Unità di lavoro come questo:

public class HRCTX : IDisposable 
{ 
    private readonly HRMainDataCTX _context; 

    public HRCTX() 
    { 
     _context = new HRMainDataCTX(); 
    } 

    public HRCTX(HRMainDataCTX context) 
    { 
     _context = context; 
    } 
    public int Save() 
    { 
     return _context.SaveChanges(); 
    } 

    public HRMainDataCTX Context 
    { 
     get { return _context; } 
    } 

    public void Dispose() 
    { 
     _context.Dispose(); 
    } 
} 

Non so come accedere al metodo (stored procedure) SEARCHEMPLOYEE attraverso UOW nel mio codice dietro.

+3

La tua domanda non è chiara, e la bontà non ci aiuterà a rispondere così com'è – Evk

+0

@Evk: Potrebbe scrivere ciò che è specificamente poco chiaro circa la mia domanda! e lo illustrerò. –

+1

Non hai commentato la risposta qui sotto dal bassfader. Quindi se non risponde alla tua domanda, puoi chiarire il perché? Esistono dei punti validi su cui non è effettivamente necessario alcun wrapper, poiché DbContext segue già il modello dell'unità di lavoro. – Evk

risposta

12

Bene, nel tuo caso devi semplicemente aggiungere un altro "Metodo proxy" per questo metodo alla tua classe HRCTX proxy/UOW, oppure - poiché HRCTX fornisce l'accesso al suo contesto sottostante - chiamalo direttamente sul contesto come questo:

HRCTX uow = new HRCTX(someContext); 
uow.Context.SEARCHEMPLOYEE(123, "123"); 

Ma volevo anche sottolineare che il DbContext rappresenta già un'Unità di modello di lavoro (in combinazione con un modello Repository, see here). Fondamentalmente stai creando un proxy per il tuo contesto, che - per quanto posso vedere in questo esempio - non aggiunge ulteriori vantaggi o funzionalità, quindi suggerirei di pensare almeno a usare direttamente il tuo HRMainDataCTX e magari a liberarti dello HRCTX classe.

+0

quindi devo aggiungere un riferimento al mio DAL.dll per accedere al contesto e questo è rendere il 'UOW' assurdo –

+0

' il tipo è definito in un assembly che non è referenziato. è necessario aggiungere un riferimento' –

+0

Uno dei costruttori pubblici della classe 'HRCTX' prende un' HRMainDataCTX' come parametro, quindi è già necessario fare riferimento a DAL.dll. Sono d'accordo con @bassfader: con solo il codice che hai fornito non vedo alcun vantaggio sull'uso diretto di DbContext. I due approcci proposti sono le uniche alternative a cui riesco a pensare. –

8

Potrebbe essere necessario implementare i repository insieme al modello di lavoro Unità di lavoro se si desidera incapsulare DbContext e la propria logica aziendale. (As suggested in the AspNet guidelines)

in modo generico, la vostra unità di lavoro in grado di gestire i repository così:

public class HRCTX : IDisposable 
{ 
    private readonly HRMainDataCTX _context; 
    private Dictionary<Type, object> Repositories { get; set; } 


    public HRCTX() 
    { 
     _context = new HRMainDataCTX(); 
     this.Repositories = new Dictionary<Type, object>(); 
    } 


    //Get and add a repository to the dictionary if ot does not exist 
    public IRepository<TEntity> GetNonGenericRepository<TEntity, TRepository>() where TEntity : class 
    { 
     if (this.Repositories.Keys.Contains(typeof(TRepository))) 
     { 
      return this.Repositories[typeof(TRepository)] as IRepository<TEntity>; 
     } 
     var repoType = typeof(TRepository); 
     var constructorInfo = repoType.GetConstructor(new Type[] { typeof(DbContext)}); 
     IRepository<TEntity> repository = (IRepository<TEntity>) constructorInfo.Invoke(new object[] { this._context}); 
     this.Repositories.Add(typeof(TRepository), repository); 
     return repository; 
    } 

public IRepository<TEntity> GetGenericRepository<TEntity>() where TEntity :  class 
    { 
     if (this.Repositories.Keys.Contains(typeof(TEntity))) 
     { 
      return this.Repositories[typeof(TEntity)] as IRepository<TEntity>; 
     } 

     IRepository<TEntity> repository = new Repository<TEntity>(this._context); 
     this.Repositories.Add(typeof(TEntity), repository); 
     return repository; 
    } 


} 

L'interfaccia e la classe base di repository:

public interface IRepository<TEntity> where TEntity : class 
{ 
    TEntity Find(Expression<Func<TEntity, bool>> match); 
} 

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class 
{ 
    protected DbContext Context { get; set; } 

    public Repository(DbContext context) 
    { 
     this.Context = context; 
    } 
    public TEntity Find(Expression<Func<TEntity, bool>> match) 
    { 
     return Context.Set<TEntity>().SingleOrDefault(match); 
    } 
} 

Ora è la parte dove hai chiaramente incapsulato la tua logica aziendale:

public class EmployeeRepository : Repository<Employee> 
{ 

    public EmployeeRepository(DbContext context) : base(context) { 

    } 
    public override Employee Find(Expression<Func<TEntity, bool>> match) 
    { 
     // You can either use the base class method or implement your custom logic 
    } 

    //This is where you encapsulate your business logic 
    public Employee FindSpecific(Nullable<decimal> employeeNum, string employeeName){ 
     return this.Context.SEARCHEMPLOYEE(employeeNum, employeeName); 
    } 
} 

Quindi tu puoi usare la tua unità di lavoro per accedere alla tua logica di business in un modo di progettazione basato sul dominio.

HRCTX unitOfWork= new HRCTX(dbContext); 
unitOfWork.GetNonGenericRepository<Employee, EmployeeRepository>().FindSpecific(1337,"1337"); 

Può sembrare troppo per quello che vi aspettavate come una risposta, ma penso che è necessario strutturare l'applicazione in questo modo se non si vuole esporre DbContext/Dal direttamente.

Spero che aiuti!