2013-07-17 26 views
13

Şu anda Genel Çerçeve ve Çalışma Düzeni Birimi ile Entity Framework kullanıyorum. Modelim, this articleEntity Framework 5 ile bir Genel Depo kullanmalı mıyım?

'da açıklanan yönteme benzer. Genel Depoları geçmişte kullandım ve sağlayabildiği global işlevselliği gerçekten çok seviyorum. Ancak, Entity Framework ile kullanıldığında her gün daha fazla sorunla karşılaşıyorum. Ebeveyn/Çocuk/Kavşak ilişkilerini ele alırken bu problemler daha da artmaktadır.

EF ile bir Jenerik Depo kullanmak kötü bir tada sahip olmaya başlıyor ve EF ile bir Jenerik Depo kullanmak yanlış bir yaklaşım olduğunu düşünüyorum.

Birisi beni doğru yöne yönlendirmeye yardım edebilir mi?

+2

Bu hedef genel depo/UOW sahip olduğunu ne olduğuna bağlıdır. DbSet 'seçeneğini zaten bir genel depo olarak ve" DbContext "(UCS) 'iniz UoW'nuz olarak düşünürse, bu kavramları kopyalamak sizin olabilir. Başka bir soyutlama seviyesine sahip olma pahasına, testi daha kolay hale getirebilir. Bunu Repo/UoW'm için kullanıyorum ve test için http://effort.codeplex.com kullanıyorum – Matthew

+0

Genel Makamı kullanmanın tek gerçek amacı Global, Jenerik CRUD Yöntemleri kullanmaktır. – Lando

+1

'DbSet <>' zaten bunları gerçekleştirir. Genel bir depoda test yapmak daha kolaydır ve eğer önemli ise Entity Framework'e olan bağımlılığı ortadan kaldırır. – Matthew

cevap

5

Bu makalenin yaklaşımı gerçekten bir acı haline gelebilecek bir şeydir, çünkü zaten bir genel depoya ve EF'de genel bir IUnitOfWork'a sahip olursunuz ve her tür için belirli bir depo oluşturmak yalnızca jenerikin faydasını kaldırır!

Burada genel bir Havuzum ve IUnitOfWork'umun nasıl bir örnek olduğunu gönderiyorum, bununla birlikte çok güzel bir deponuz olabilir!

public interface IUnitOfWork : IDisposable 
{ 
    void Save(); 
    void Save(SaveOptions saveOptions); 
} 

public interface IRepository<TEntity> : IDisposable where TEntity : class 
{ 
    IUnitOfWork Session { get; } 
    IList<TEntity> GetAll(); 
    IList<TEntity> GetAll(Expression<Func<TEntity, bool>> predicate); 
    bool Add(TEntity entity); 
    bool Delete(TEntity entity); 
    bool Update(TEntity entity); 
    bool IsValid(TEntity entity); 
} 

Ve benzeri uygulama şey:

public class Repository : Component, IRepository 
{ 

    protected DbContext session; 

    public virtual IUnitOfWork Session 
    { 
     get 
     { 
      if (session == null) 
       throw new InvalidOperationException("A session IUnitOfWork do repositório não está instanciada."); 
      return (session as IUnitOfWork); 
     } 
    } 

    public virtual DbContext Context 
    { 
     get 
     { 
      return session; 
     } 
    } 

    public Repository(IUnitOfWork instance) 
    { 
     SetSession(instance); 
    } 

    public IList<TEntity> GetAll<TEntity>() where TEntity : class 
    { 
     return session.Set<TEntity>().ToList(); 
    } 

    public IList<TEntity> GetAll<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class 
    { 
     return session.Set<TEntity>().Where(predicate).ToList(); 
    } 

    public bool Add<TEntity>(TEntity entity) where TEntity : class 
    { 
     if (!IsValid(entity)) 
      return false; 
     try 
     { 
      session.Set(typeof(TEntity)).Add(entity); 
      return session.Entry(entity).GetValidationResult().IsValid; 
     } 
     catch (Exception ex) 
     { 
      if (ex.InnerException != null) 
       throw new Exception(ex.InnerException.Message, ex); 
      throw new Exception(ex.Message, ex); 
     } 
    } 

    public bool Delete<TEntity>(TEntity entity) where TEntity : class 
    { 
     if (!IsValid(entity)) 
      return false; 
     try 
     { 
      session.Set(typeof(TEntity)).Remove(entity); 
      return session.Entry(entity).GetValidationResult().IsValid; 
     } 
     catch (Exception ex) 
     { 
      if (ex.InnerException != null) 
       throw new Exception(ex.InnerException.Message, ex); 
      throw new Exception(ex.Message, ex); 
     } 
    } 

    public bool Update<TEntity>(TEntity entity) where TEntity : class 
    { 
     if (!IsValid(entity)) 
      return false; 
     try 
     { 
      session.Set(typeof(TEntity)).Attach(entity); 
      session.Entry(entity).State = EntityState.Modified; 
      return session.Entry(entity).GetValidationResult().IsValid; 
     } 
     catch (Exception ex) 
     { 
      if (ex.InnerException != null) 
       throw new Exception(ex.InnerException.Message, ex); 
      throw new Exception(ex.Message, ex); 
     } 
    } 

    public virtual bool IsValid<TEntity>(TEntity value) where TEntity : class 
    { 
     if (value == null) 
      throw new ArgumentNullException("A entidade não pode ser nula."); 
     return true; 
    } 

    public void SetSession(IUnitOfWork session) 
    { 
     SetUnitOfWork(session); 
    } 

    protected internal void SetUnitOfWork(IUnitOfWork session) 
    { 
     if (!(session is DbContext)) 
      throw new ArgumentException("A instância IUnitOfWork deve um DbContext."); 
     SetDbContext(session as DbContext); 
    } 

    protected internal void SetDbContext(DbContext session) 
    { 
     if (session == null) 
      throw new ArgumentNullException("DbContext: instance"); 
     if (!(session is IUnitOfWork)) 
      throw new ArgumentException("A instância DbContext deve implementar a interface IUnitOfWork."); 
     this.session = session; 
    } 

} 
+0

Eklemede, yakalama noktasının noktası nedir? Ayrıca, neden session.Set () .Ad (varlık)? – jcmcbeth

+0

Soru genel kullanım hakkındaydı, bu yüzden bunun açıklamaya yardımcı olması için sadece bir örnek olduğunu aklınızdan çıkarmayın. Bu sorunun amacı değil. Try catch'unun noktası, daha genel bir hata yerine yükseltilen iç istisnayı gösterebilmektir. Ayrıca Set () .Add (varlık) kullanarak bu durumda çalışır, ancak genel sürümü kullanamayacağımız bir nokta vardır (örneğin mirasınız varsa ve .TypeOf <> kullanmak zorundaysanız) –

+0

istisnayı yeniden düşünün, sonra sadece "atmak" diyebilirsiniz, yeni bir istisna atmak mevcut çağrı yığınının atılmasına neden olur. Http://stackoverflow.com/questions/881473/why-catch-and-rethrow-exception-in-c adresine bakın. Ayrıca içsel istisnayı yeniden düzenlemeyi de kabul etmiyorum, çünkü bu yöntemi arayan herkes içsel istisnayı da kolayca kontrol edebilir, ancak bu kodla onlara seçenek sunmuyorsunuz. – jcmcbeth

İlgili konular