2010-06-30 3 views
2

J'essaie d'écrire un référentiel générique pour mon application Entity Framework. Voici mon code prototype:Création d'un référentiel générique pour une application Entity Framework

Interface

public interface IDomainRepository 
    { 
     T GetById<T>(int id, Expression<Action<T>> idx) 
    } 

et le dépôt:

public class DomainRepository : IDomainRepository 
    { 
     private readonly DatabaseDataContext _ctx; 

     public DomainRepository(DatabaseDataContext ctx) 
     { 
      _ctx = ctx; 
     } 

     public T GetById<T>(int id, Expression<Action<T>> idx) 
     { 
      return _ctx.GetTable(typeof (T)).SingleOrDefault(idx); 
     } 
    } 

Le code de test ci-dessus est ce qui ne fonctionne pas. Mais ce que je voudrais être en mesure de faire est la suivante:

var repository = new DomainRepository(myContext); 

var client = repository.GetById<tbl_Clients>(23, c => c.clientId); 

Donc, fondamentalement, je veux obtenir une entité client de la base de données en passant dans l'id plus un lambda dire GetById ce que la colonne id est. En outre, je n'ai aucune idée de la façon dont j'exécuterais le lambda en utilisant l'identifiant passé.

Quelqu'un peut-il m'aider?

EDIT:

Je suis vraiment proche. J'ai changé GetById:

public T GetById<T>(int id, Expression<Func<T, object>> idx) 

et je peux maintenant l'appeler comme ceci:

var g = repository.GetById<tbl_Client>(23, c => c.cl_id); 

mais je ne sais pas comment utiliser IDX et vérifier sa valeur contre l'id passé:

public T GetById<T>(int id, Expression<Func<T, object>> idx) 
     { 
      //var col = idx.Compile().Invoke(T); 
      // How do I check if the column passed to "idx" is equal to id? 

      return default(T); 
     } 

EDIT: Pensez que cela fonctionne maintenant. Voici mon code entier, plus test:

public interface IDomainRepository 
    { 
     T GetById<T>(int id, Expression<Func<T, object>> idx) where T : class; 

     IEnumerable<T> GetAll<T>() where T : class; 
     IEnumerable<T> Query<T>(Expression<Func<T, bool>> filter) where T : class; 
     IEnumerable<T> Query<T>(ISpecification<T> filter) where T : class; 

     void Add<T>(T entity) where T : class; 
     void Delete<T>(T entity) where T : class; 
     Table<T> GetTable<T>() where T : class; 
    } 

public class DomainRepository : IDomainRepository 
    { 
     private readonly DatabaseDataContext _ctx; 

     public DomainRepository(DatabaseDataContext ctx) 
     { 
      _ctx = ctx; 
     } 

     public T GetById<T>(int id, Expression<Func<T, object>> idx) where T : class 
     { 
      return (from i in GetAll<T>() 
        let h = idx.Compile().Invoke(i) 
        where Convert.ToInt32(h) == id 
        select i).SingleOrDefault(); 
     } 

     public IEnumerable<T> GetAll<T>() where T : class 
     { 
      return GetTable<T>().ToList(); 
     } 

     public IEnumerable<T> Query<T>(Expression<Func<T, bool>> filter) where T : class 
     { 
      return GetTable<T>().Where(filter); 
     } 

     public IEnumerable<T> Query<T> (ISpecification<T> filter) where T : class 
     { 
      return GetTable<T>().Where(filter.Predicate); 
     } 

     public void Add<T> (T entity) where T : class 
     { 
      GetTable<T>().InsertOnSubmit(entity); 
     } 

     public void Delete<T> (T entity) where T : class 
     { 
      GetTable<T>().DeleteOnSubmit(entity); 
     } 

     public Table<T> GetTable<T>() where T : class 
     { 
      return _ctx.GetTable(typeof(T)) as Table<T>; 
     } 
    } 


var repository = new DomainRepository(_ctx); 

var g = repository.GetById<tbl_Client>(1, c => c.cl_id); 

Je vais continuer à tester ceci pour voir si c'est OK.

Cheers. Jas.

Répondre

0

OK, je pense avoir la version finale, aura besoin d'un peu plus de tests que:

public T GetById<T>(int id, Func<T, int> idx) where T : class 
     { 
      return (from i in GetAll<T>() 
        where idx(i) == id 
        select i).SingleOrDefault(); 
     } 
+0

Vérifiez SQL généré par cette méthode. Autant que je sache, cela peut entraîner la matérialisation de toute la table et l'application de Linq aux objets. –

-1

Vous pouvez simplement exposer le IQueryable à travers des calques.

utilisateurs IQueryable {get;}

Alors vous pouvez faire quelque chose comme ceci dans votre code ui:

BLLContext.Users.Where (c => c.Username == "foo"); BLLContext aura un contexte DAL sous-jacent qui expose le IQueryable.

+1

Merci pour votre suggestion, mais je veux le dépôt soit générique, il ne peut donc pas savoir " Utilisateurs "d'une manière concrète. Salut quand même. –

Questions connexes