Comment mapper des classes de modèle Entity Framework avec la classe de couche de gestion dans une architecture à plusieurs niveaux – ASP.NET-MVC

Je travaille sur une architecture e-tier au sein de la structure MVC (ASP.NET MVC5, Entity Framework 6). Mon application est divisée en trois sous-projets: couche métier, couche access-données, référentiel (y compris référentiel et unité de travail) et application Web ASP.NET MVC. J’ai du mal à comprendre le mappage entre les données commerciales et le modèle de structure d’entité. par exemple, si j’ai la classe de modèle User dans le entity framework

DAL – Modèle d’utilisateur

[Table("User")] public class User { public User() { } [Key] public int UserID { get; set; } [SsortingngLength(250)] [Required] public ssortingng FirstName { get; set; } [SsortingngLength(250)] [Required] public ssortingng LastName { get; set; } [Required] public int Age { get; set; } [SsortingngLength(250)] [Required] public ssortingng EmailAddress { get; set; } public ICollection UserInGroup { get; set; } } 

et dans la couche métier, j’ai classe d’utilisateurs

BLL – Classe d’utilisateurs

 public class User { private ssortingng userID; private ssortingng firstName; private ssortingng lastName; private int age; private ssortingng emailAddress; public ssortingng UserID { get { return userID; } set { userID = value; } } public ssortingng FirstName { get { return firstName; } set { firstName = value; } } public ssortingng LastName { get { return lastName; } set { lastName = value; } } public int Age { get { return age; } set { age = value; } } public ssortingng EmailAddress { get { return emailAddress; } set { emailAddress = value; } } public void GetAllUser() { List _user = new List(); using (var _uow = new UserManagement_UnitOfWork()) { _user = (from u in _uow.User_Repository.GetAll() select u).ToList(); } } } 

Comment je mappe ensemble et deuxièmement; En référence à la méthode GetAllUser (), je dois toujours utiliser la classe de modèle utilisateur de DAL afin d’obtenir tous les utilisateurs de la firebase database, où se trouvent actuellement mes connaissances; chaque couche doit être indépendante l’une de l’autre et j’ai une couche d’abstraction, c’est-à-dire un référentiel entre la couche d’access aux données et la couche de gestion. Je suis un peu confus du fait que les deux concepts travaillent ensemble. Suis-je sur la bonne voie ou manque quelque chose. besoin également de réponse pratique sur la couche de gestion utilisateur.

    Vous pouvez simplement le faire en utilisant AutoMapper Installez-le via Nuget:

     PM> Install-Package AutoMapper 

    et tout ce que vous avez à faire est de configurer AutoMapper pour mapper des objects similaires à votre place.

     Mapper.CreateMap(); 

    Vous pouvez convertir des objects n’importe où comme ceci:

     BLL.User bll_User = Mapper.Map(dal_user); 

    Votre question concerne davantage le design / l’architecture, qui n’a pas de solution unique. Je peux tout au plus partager quelques suggestions et que vais-je faire habituellement dans une stack ASP.NET MVC + Entity Framework assez typique:

    1. Assurez-vous que votre classe BLL.User le principe de responsabilité unique.

    Votre classe BLL.User ne doit pas se préoccuper de la façon de récupérer DAL.User de la firebase database via Entity Framework / Unit of Work. Vous devriez simplement avoir une autre classe / couche qui sera responsable de cela:

     public interface IUserRepository { IEnumerable GetAllUsers(); } 

    Puis une autre classe pour implémenter IUserRepository :

     public class UserRepository : IUserRepository { private readonly UserManagement_UnitOfWork _unitOfWork; public UserRepository(UserManagement_UnitOfWork unitOfWork) { _unitOfWork = unitOfWork; } public IEnumerable GetAllUsers() { return from u in _unitOfWork.User_Repository.GetAll() select u; } } 

    Cela supprime la dépendance de votre utilisateur BLL.User à la classe UserManagment_UnitOfWork et facilite les tests / moquages ​​(des tests unitaires peuvent être écrits pour IUserRepository mémoire).

    Ensuite, à partir de votre contrôleur, chaque fois qu’il est nécessaire de récupérer BLL.Users , vous injectez simplement une instance de IUserRepository dans le constructeur du contrôleur:

     public class UserController { private readonly IUserRepository _userRepository; public UserController(IUserRepository userRepository) { _userRepository = userRepository; } public ActionResult Index() { // Simple example using IEnumerable as the view model return View(_userRepository.GetAllUsers().ToList()); } } 

    2. Comment mapper DAL.User à BLL.User

    C’est en fait assez similaire au point 1, vous pouvez simplement avoir une autre paire interface / classe:

     public interface IUserMapper { BLL.User MapUser(DAL.User); } public class UserMapper : IUserMapper { public BLL.User MapUser(DAL.User user) { return new BLL.User { FirstName = user.FirstName, LastName = user.LastName, Age = user.Age // etc... }; } } 

    Ou, si vous pensez que l’écriture de code de mappage est fastidieuse, envisagez d’utiliser AutoMapper pour que votre code devienne Mapper.Map(user)

    Points bonus

    1. Vous pouvez ignorer ces champs private dans BLL.User et les convertir en propriétés automatiques.
    2. Vous pouvez append des atsortingbuts dérivés de ValidationAtsortingbute pour faciliter la validation dans votre application ASP.NET MVC.
     public class User { public ssortingng UserId { get; set; } [Required] public ssortingng FirstName { get; set; } public ssortingng LastName { get; set; } [Range(0, int.MaxValue)] public int Age { get; set; } [EmailAddress] public ssortingng EmailAddress { get; set; } } 

    Tout d’abord, il n’y a pas besoin de couche de référentiel ni de couche d’access aux données. Ces deux couches ont le même objective: append une couche d’abstraction pour utiliser votre stockage persistant. Bien qu’ils aient des concepts différents

    1. En règle générale, le motif de référentiel vous permet de travailler avec votre firebase database comme s’il s’agissait d’une collection en mémoire. La plupart du temps, il expose les méthodes de base CRUD (create read update et delete) avec d’autres extensions telles que la méthode GetAll , etc. Il s’agit d’une description très simplifiée, mais les ressources disponibles concernant ce modèle sont suffisantes, par exemple .
    2. La couche d’access aux données ajoute également une abstraction mais de manière beaucoup plus subjective. En gros, il contient toute l’API permettant d’accéder à votre firebase database. Par exemple, pour votre classe User, elle peut avoir des méthodes telles que GetUserByName , GetUserById , RemoveUser , GetAllActiveUsers , etc.

    De plus, l’unité de travail ne doit pas nécessairement être implémentée dans le référentiel / DAL. Puisqu’une même unité de travail peut contenir la modification de plusieurs entités ou des demandes à des services externes. À mon avis, BLL serait un endroit plus approprié pour UoW ​​car, dans la plupart des cas, vous pouvez considérer une seule action commerciale (une méthode dans BL) comme un UoW.

    Maintenant, quand c’est un peu plus clair ( j’espère ). Votre référentiel / DAL doit renvoyer uniquement les entités commerciales et non les classes générées par la firebase database (si elles sont différentes) et toute la logique de mappage doit être encapsulée dans les couches de référentiel / DAL. Par exemple, la méthode GetUserById doit renvoyer une BLL - User Class et non une classe utilisateur générée par EF dans ce cas, qui peut être une classe interne de la couche Repository / DAL.

    Pour gérer les mappages entre ces classes, vous pouvez utiliser différentes bibliothèques telles que ValueInjecter ou AutoMapper, qui sont vraiment géniales et peuvent faciliter votre développement.