2012-11-08 4 views
5

J'ai une implémentation de référentiel générique. J'utilise asp.net mvc C#, code premier cadre de l'entité.Référentiel générique avec fonction de suppression logicielle

J'ai créé une interface nommée ISoftDelete:

public interface ISoftDelete 
{ 
    bool IsDeleted { get; set; } 
} 

Supprimer et j'ai mis GetById dans mon référentiel de base comme suit:

public virtual void Delete(T entity) 
    { 
     if (entity is ISoftDelete) 
     { 
      ((ISoftDelete)entity).IsDeleted = true; 
     } 
     else 
     { 
      dbset.Remove(entity); 
     } 
    } 

    public virtual T GetById(long id) 
    { 
     T obj = dbset.Find(id); 
     if (obj is ISoftDelete) 
     { 
      if (((ISoftDelete)obj).IsDeleted) 
       return null; 
      else 
       return obj; 
     } 
     else 
     { 
      return obj; 
     } 
    } 

Maintenant, j'ai 2 questions.

1) Cette approche est-elle une bonne approche? Des problèmes liés à la performance?

2) Ma fonction GetAll d'origine dans le référentiel de base est comme ceci:

public virtual IEnumerable<T> GetAll() 
    { 
      return dbset.ToList(); 
    } 

Comment vais-je modifier afin de répertorier les enregistrements où IsDeleted == false, lorsque T est dérivé de ISoftDelete?

Merci!

Répondre

4

1) Il ne semble pas correct pour vérifier if (entity is ISoftDelete) chaque fois que vous devez savoir. Si vous êtes sûr que vous n'allez pas vérifier ailleurs, c'est peut-être bien. En termes de performances, il serait préférable d'éliminer les enregistrements ayant IsDeleted == true et de ne jamais les récupérer depuis db. Vous devrez peut-être dériver un nouveau référentiel de base qui remplace ces méthodes et implémente de nouvelles logiques pour l'objet ISoftDelete.

public abstract class BaseRepository<T> 
{ 
    // protected dbset; 

    public virtual void Delete(T entity) 
    { 
     dbset.Remove(entity); 
    } 

    public virtual T GetById(long id) 
    { 
     return dbset.Find(id); 
    } 

    public virtual IEnumerable<T> GetAll() 
    { 
     return dbset.ToList(); 
    } 
} 

public abstract class SoftDeleteRepository<T> : BaseRepository<T> where T : ISoftDelete 
{ 
    public override void Delete(T entity) 
    { 
     entity.IsDeleted = true; 
    } 

    public override T GetById(long id) 
    { 
     return (from t in dbSet 
       where !t.IsDeleted && t.Id == id select t) 
       .FirstOrDefault(); 
    } 

    public override IEnumerable<T> GetAll() 
    { 
     return (from t in dbset where !t.IsDeleted select t).ToList(); 
    } 
} 

public static class RepositoryFactory 
{ 
    public static BaseRepository<T> GetInstance<T>() 
    { 
      // pseudo code 
      if (typeof(T) implements ISoftDelete) 
       return repository of T which extends SoftDeleteRepository 
      return repository of T which extends BaseRepository 
    } 
} 

2) peut-être quelque chose comme

return (from t in dbset where 
     (t is ISoftDelete && !(t as ISoftDelete).IsDeleted) || 
     !(t is ISoftDelete)) 
.ToList(); 
+0

+1 solution agréable –

+0

public override T GetById (longue id), cette fonction renvoie une erreur sur t.Id. – SherleyDev

+0

Si vous mettez une méthode 'GetById (long id)' dans votre BaseRepository, cela signifie que vous supposez que toute instance d'entité dans votre projet doit avoir une propriété 'long Id'. Afin de satisfaire cette exigence, vous pouvez définir une interface telle que 'IEntity {long Id {get; }} 'et l'appliquer à toutes les entités. Et dérivez votre 'ISoftDelete' de cette interface. 'interface ISoftDelete: IEntity {bool IsDeleted {get; ensemble; }} '. Et maintenant votre SoftDeleteRepository est sûr que chaque instance T aura les propriétés Id et IsDeleted. –

0

Votre approche me semble bonne. Je pense qu'il n'y a pratiquement aucune perte de performance sauf le test sur la condition de suppression, ce qui est correct. Pour getAll vous pouvez essayer ce code:

public virtual IEnumerable<T> GetAll() 
    { 
     var queryable = dbset; 
     if (typeof(ISoftDelete).IsAssignableFrom(typeof(T))) 
     { 
      queryable = queryable.Where(q => q.IsDeleted == false); 
     } 

     return queryable.ToList(); 
    } 
Questions connexes