Entités de données> Objets de domaine> ViewModels, chacun avec des structures de données radicalement différentes

C’est en quelque sorte une question générique en ce qui concerne le mappage entre des entités de données, des objects de domaine et des modèles de vue. Je ne le demande peut-être pas correctement, mais j’espère pouvoir le comprendre. Ci-dessous un problème simplifié.

Imaginez que j’ai un modèle Entity Framework qui mappe 1: 1 à mes tables de firebase database, mais mes objects de domaine peuvent ne pas être identiques et mon ViewModel est radicalement différent à nouveau. Comme pseudo-exemple:

Entités de firebase database / EF:

  • AdhésionCompte
  • MembershipAccountExtraInfo

Domaine:

  • Compte
  • Profil
  • Préférences

ViewModel:

  • UserProfileModel

Supposons que je dois afficher un UserProfileModel comportant les éléments suivants: Nom d’utilisateur ( de MembershipAccount ), SignupDate ( de MembershipAccount ), FullName ( de MembershipAccountExtraInfo ) et TimeZone ( de MembershipAccountExtraInfo ).

De quel type de relations pourrais-je avoir besoin ici et de quel type de mécanismes de cartographie? Est-il courant d’avoir quelque chose comme un AccountMapper qui prend à la fois un MembershipAccount et un MembershipAccountExtraInfo et retourne un compte? Je suis un peu coincé sur le mappage lorsque plusieurs objects sont nécessaires pour créer une seule entité de domaine, et inversement.

Si cela aide: je conçois une API pour la gestion des comptes utilisateur, des profils utilisateur, des préférences utilisateur, etc., mais les tables de la firebase database sont omniprésentes. Il peut être nécessaire de créer un seul profil utilisateur à partir de données regroupant 4 à 5 tables et 2 bases de données. Il n’y a pas de mappage 1: 1 entre mes tables de firebase database et tout object de domaine (logique).

Merci!

J’aime travailler en maintenant les objects de mon domaine le plus près possible des objects qu’ils représentent. Ce que je veux dire par là, c’est que si un compte a des préférences, l’object Account domaine doit contenir une propriété Preferences , probablement représentée par une collection d’objects Preference . Si rien d’autre, cela aide les utilisateurs à comprendre facilement la structure de données de l’application.

Pour ce qui est de la construction des modèles de vue, c’est le bit le plus simple: vous n’ajoutez que des propriétés pour tout ce qui est requirejs. Les types de propriétés dont vous auriez besoin dépendraient vraiment de la manière dont vous avez structuré vos objects de domaine.

Si votre vue présente les exigences que vous avez mentionnées dans votre question et que vous modélisez étroitement vos objects de domaine sur les objects qu’ils représentent, vous aurez simplement besoin d’un object Account , car il contiendrait les objects Preference et Profile intérieur. il.

Enfin, le seul «mappage» à effectuer peut être effectué avec une requête LinQ à l’aide d’Entity Framework. C’est à ce stade que je rejoint les tables et extrait toutes les données dont j’ai besoin pour l’object sur lequel je travaille. Voici un exemple d’instanciation d’objects à partir de données provenant de trois tables (avec LinQ2SQL ):

 public AudioTracks GetAudioTracks(AudioTrackSearchOptions searchOptions) { AudioTracks audioTracks; using (MidasDataContext dataContext = DataContext) { audioTracks = new AudioTracks( from audioTrack in dataContext.DbAudioTracks join masterTrack in dataContext.DbMasterTracks on audioTrack.MasterTrackId equals masterTrack.Id join masterTrackArtist in dataContext.DbDataLists on masterTrack.ArtistId equals masterTrackArtist.Id orderby ssortingng.Concat(masterTrack.Title, " (", audioTrack.Mix, ") - ", masterTrackArtist.Text) where (searchOptions.IsInactiveAudioTrackIncluded || audioTrack.IsActive) && (searchOptions.IsDeletedAudioTrackIncluded || !audioTrack.IsDeleted) select new AudioTrack(audioTrack.Id, masterTrack.Id, audioTrack.Isrc, masterTrack.Title, masterTrackArtist.Text, audioTrack.Mix, audioTrack.IsContentExplicit, audioTrack.IsActive, audioTrack.IsDeleted)); } audioTracks.Sort(a => a.TitleWithMix); return audioTracks ?? new AudioTracks(); } 

MISE À JOUR >>>

Pour étendre mon exemple AudioTracks et revenir en arrière, la méthode GetAudioTracks trouve dans un projet appelé DataProviders . Il est appelé à partir d’une méthode GetAudioTracks d’une classe DataController , qui ajoute simplement des commentaires à l’utilisateur et des options de nouvelle tentative. À son tour, cela est appelé par un TracksModel dans le projet Models qui ne contient qu’une sous-section de méthodes de la classe DataController qui se rapportent aux différents types de pistes de l’application.

Enfin, AudioTracksViewModel dans le projet ViewModels appelle la méthode TracksModel.GetAudioTracks lors de l’initialisation, ce qui se produit lorsque AudioTracksView est chargé par l’utilisateur. AudioTracksView a un ListBox sur la gauche contenant tous les objects AudioTrack qui correspondent aux sélections de filtre et de recherche des utilisateurs. La droite de l’écran contient les champs de la AudioTrack sélectionnée. Voici à quoi ça ressemble (si le lien semble cassé, vous pouvez voir l’image ici ):

AudioTracksView

Les champs les plus transparents avec un Button édition à droite sont des champs en lecture seule connectés aux collections. Le Button édition ouvre une boîte de dialog permettant à l’utilisateur de saisir plusieurs éléments, qui sont ensuite résumés dans le champ. Tous les objects de l’application ont des vues similaires plus ou moins complexes.