3

Je fais un site intranet en utilisant ASP.NET MVC et SQL Server 2012. Je fais un référentiel et l'architecture avec Oignon Architecture. Mon problème est que la société dans laquelle je travaille, a déjà plusieurs DB de serveur dans lesquels les tables n'ont aucune relation entre elles. Au lieu de cela, il existe des tables pour cartographier ces relations. Par exemple une table Utilisateur, et une table Document ont une table User_joint_Document pour faire une relation, contenant à la fois les IDs (IDDocument et IDUser). Maintenant, quand j'écris mon dépôt générique:Entity Framework et Repository Pattern difficultés conceptuelles

class Repository<T> : IRepository<T> where T : class 

le problème est le T de type générique n'a pas de sens et je ne peux pas affecter les valeurs dans mon modèle à l'aide des requêtes EF ce qui est normal, et ce serait génial serait ont une BaseEntity de classe parente d'avoir ID définis pour chaque table, je peux écrire:

class Repository<T> : IRepository<T> where T : BaseEntity 

Et tous mes modèles de table hériterait de BaseEntity. Mais cela signifierait aussi réécrire l'ensemble de la DB de manière relationnelle et mapper chaque DB POCO manuellement (corrigez-moi si je me trompe), et je n'ai pas la compétence pour le faire (il y a plus de 300 tables dans les différents DBs du serveur et je manque de connaissances et d'expérience pour faire ce genre d'opération).

Existe-t-il un moyen de conserver ma structure de base de données d'origine et d'écrire un référentiel générique? Comment irait-on faire ça?

EDIT Pour clarifier ma question, car @saeb a répondu partiellement à ma question. Puis-je avoir un repo générique sans avoir de classe parent pour mes DB POCO? Ou en ai-je besoin pour avoir alors UN seul référentiel pour les gouverner tous? Par exemple:

class Repository<T>:IRepository<T> where T : class 
{ 
    private readonly ApplicationContext context; 
    private DbSet<T> entities; 
    public Repository(PrincipalServerContext context) 
    { 
     this.context = context; 
     entities = context.Set<T>(); 
    } 
    public T Get(long id) 
    { 
    return entities.SingleOrDefault(s => s.IDUser == id); 
    //This does not work, IDUser isn't recognized 

    } 

Merci pour votre aide!

+0

l'exemple que vous avez donné de '' Users' et Documents' est correct dans la base de données. Un utilisateur peut avoir de nombreux documents, vous avez donc besoin d'une table de jonction de 'User_joint_Document'. C'est exactement comme cela qu'une base de données relationnelle devrait être structurée. – melkisadek

+1

Mais si vous utilisez Onion Architecture, il y a un paquet qui crée des dépôts automatiquement pour vous, il vous suffit de les enregistrer dans DataOnion. –

+0

@melkisadek Bah! Voilà à quel point je suis à travailler sur les DB. J'aurais pensé que vous auriez quelque chose comme une relation 1-1 entre les deux tables ou quelque chose comme ça? Peut-être que ce rapport est une table réelle? Vraiment pas mon côté fort. Si je crée une classe parente avec des ID, que devient cette table de relations? Comme il avait IDDocument et IDUser, mais maintenant je n'aurais ID que de la classe parente –

Répondre

3

... a plusieurs blocs de données de serveur dans lequel les tables sont dépourvues de relations entre eux ...

Mais ils faire ont une relation, une relation Many-to-Many, qui est défini par ce troisième table de correspondance (si c'est une relation définie correctement est un autre sujet)

... le problème est le T de type générique n'a pas de sens et je ne peux pas affecter les valeurs dans mon modèle en utilisant des requêtes EF ...

Pourquoi pas et pourquoi pas vous? compte tenu de vos exemples de table, vous auriez deux entités, User et Document et ils avaient ressembler à ceci:

public class User 
{ 
    public int IDUser { get; set; } 

    public virtual ICollection<Document> Documents { get; set; } 

    ... 
} 

public class Document 
{ 
    public int IDDocument { get; set; } 

    public virtual ICollection<User> Users { get; set; } 

    ... 
} 

Et vous pouvez utiliser l'API couramment dans votre contexte de OnModelCreating pour établir la relation via la troisième table :

public class YourContext: DbContext 
{ 
    ... 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<User>() 
      .HasMany<Document>(u => u.Documents) 
      .WithMany(d => d.Users) 
      .Map(userJointDocument => 
       { 
        userJointDocument.MapLeftKey("IDUser"); 
        userJointDocument.MapRightKey("IDDocument"); 
        userJointDocument.ToTable("User_joint_Document"); 
       }); 
    } 

    ... 
} 

et vous pouvez alors interroger User s et Document s dans votre dépôt comme vous le feriez s'il y avait un lien direct entre eux. Here sont more bon sources pour en savoir plus à ce sujet si vous aimez.

+0

Merci pour cette réponse précise et bons docs. Je l'ai fait mais j'ai toujours des problèmes dans mon repo, je ne peux pas reconnaître les identifiants. J'ai édité ma question pour montrer à quoi ressemble mon rapport –

+0

Vous ne pouvez pas étiqueter bizarrement –

1

Pour autant que je peux voir votre problème, il y a maintenant moyen d'y parvenir sans mettre au moins une classe de base ou d'une interface à vos entités/Poços

Vous pouvez jouer avec des expressions pour la réalisation d'un référentiel générique

public interface IEntity<T> where T : class 
{ 
    Expression<Func<T, bool>> GetByIdPredicate(long id); 
}   

public partial class User : IEntity<User> 
{ 
    public int UserID { get; set; } 

    public Expression<Func<User, bool>> GetByIdPredicate(long id) 
    { 
     return (User entity) => entity.UserID == id; 
    } 
} 

class Repository<T>:IRepository<T> where T : class, IEntity, new() 
{ 
    private readonly ApplicationContext context; 
    private DbSet<T> entities; 
    T dummyEntity; 

    public Repository(PrincipalServerContext context) 
    { 
     this.context = context; 
     entities = context.Set<T>(); 
     dummyEntity = new T(); 
    } 
    public T Get(long id) 
    { 
    return entities.SingleOrDefault(dummyEntity.GetByIdPredicate(id)); 
    } 

Il y a probablement un moyen plus propre qui supprime aussi le champ dummyEntity

+0

Oh c'est une prise très intéressante. J'ai reformulé ma question et j'ai eu une autre réponse ici, si jamais vous êtes intéressé, tout est emballé dans une méthode en utilisant les méthodes Expression: https://stackoverflow.com/questions/44591796/does-a-generic-repository- besoin d'une base-entité-classe-à-être-appliqué-partout/44592318 # 44592318 –