数据实体域对象ViewModels,每个都有截然不同的数据结构 [英] Data Entities > Domain Objects > ViewModels, each with drastically different data structures
问题描述
这是一个关于数据实体、域对象和 ViewModel 之间映射的通用问题.我可能没有问对,但希望我能理解它.下面是一个简化的问题.
This is sort of a generic question in regards to mapping between data entities, domain objects, and ViewModels. I may not be asking it right but hopefully I can make some sense of it. Below is a simplified problem.
假设我有一个实体框架模型,它以 1:1 的比例映射到我的数据库表,但我的域对象可能不相同,而我的 ViewModel 又完全不同.作为一个伪示例:
Pretend I have an Entity Framework model which maps 1:1 to my database tables, but my domain objects may not be identical, and my ViewModel is drastically different again. As a pseudo-example:
数据库/EF 实体:
- 会员帐户
- MembershipAccountExtraInfo
域:
- 帐户
- 个人资料
- 偏好设置
视图模型:
- 用户配置文件模型
假设我需要显示一个 UserProfileModel,它具有:用户名(from MembershipAccount)、SignupDate(from MembershipAccount)、FullName(from MembershipAccountExtraInfo>) 和时区(来自 MembershipAccountExtraInfo)
Let's say I need to display a UserProfileModel which has: Username (from MembershipAccount), SignupDate (from MembershipAccount), FullName (from MembershipAccountExtraInfo), and TimeZone (from MembershipAccountExtraInfo)
这里我可能需要什么样的关系,什么样的映射机制?有一个像 AccountMapper 这样的东西,它同时接受 MembershipAccount 和 MembershipAccountExtraInfo 并返回一个 Account 是不是很常见?当需要多个对象来创建单个域实体时,我有点困在映射上,反之亦然.
What sort of relationships might I need here, and what sort of mapping mechanisms? Is it common to have something like an AccountMapper that takes both a MembershipAccount and MembershipAccountExtraInfo and returns an Account? I'm a bit stuck on the mapping when several objects are needed to create a single domain entity, and vice versa.
如果有帮助:我正在设计一个 API 来管理用户帐户、用户配置文件、用户首选项等,但数据库表到处都是.可能需要从跨越 4-5 个表和 2 个数据库的数据创建单个用户配置文件.我的数据库表和任何(逻辑)域对象之间没有 1:1 映射.
If it helps: I'm designing an API for managing User Accounts, User Profiles, User Preferences, etc. but the database tables are all over the place. A single User Profile might need to be created from data spanning 4-5 tables and 2 databases. There is no 1:1 mapping between my database tables and any (logical) domain objects.
谢谢!
推荐答案
我喜欢让我的领域对象尽可能接近它们所代表的对象.我的意思是,如果一个帐户有首选项,那么域 Account
对象应该包含一个 Preferences
属性,最有可能由 Preference<的集合表示/代码> 对象.如果不出意外,这有助于用户轻松理解应用程序的数据结构.
I like to work keeping my domain objects as close to the objects that they represent as possible. What I mean by this is that if an account has preferences, then the domain Account
object should contain a Preferences
property, most likely represented by a collection of Preference
objects. If nothing else, this helps the users understand the data structure of the application easily.
至于构建视图模型,这是最简单的一点……您只需为所需的任何内容添加属性.您需要什么类型的属性实际上取决于您如何构建域对象.
As for constructing the view models, that's the easiest bit... you add just properties for anything that is required. What types of properties you would need would really depend on how you have structured your domain objects.
如果您的视图具有您在问题中提到的要求,并且您将域对象紧密地建模在它们所代表的对象上,那么根据它的声音,您只需要一个 Account
对象因为这将包含其中的 Preference
和 Profile
对象.
If your view has the requirements that you mentioned in your question and you modelled your domain objects closely on the objects that they represent, then by the sounds of it, you would just need an Account
object because that would contain the Preference
and Profile
objects inside it.
最后,唯一需要完成的映射"可以通过使用实体框架的 LinQ
查询来完成.正是在这一点上,我加入了表格并提取了我正在处理的任何对象所需的任何数据.下面是从三个表中的数据实例化对象的示例(使用 LinQ2SQL
):
Finally, the only 'mapping' that needs to be done can be done with a LinQ
query using the Entity Framework. It is at this point that I join the tables and pull whatever data that I need for whichever object I am working on. Here is an example of instantiating objects from data from three tables (using 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 string.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();
}
<小时>
更新>>>
UPDATE >>>
扩展我的 AudioTracks
示例并向后工作,GetAudioTracks
方法位于名为 DataProviders
的项目中.它从 DataController
类中的 GetAudioTracks
方法调用,该类只添加用户反馈和重试选项.它又由 Models
项目中的 TracksModel
调用,该项目仅包含来自 DataController
类的与各种类型相关的方法的子部分应用程序中的曲目.
Extending my AudioTracks
example and working backwards, the GetAudioTracks
method is in a project called DataProviders
. It is called from a GetAudioTracks
method in a DataController
class which just adds user feedback and re-try options. That in turn is called by a TracksModel
in the Models
project which just contains a subsection of methods from the DataController
class that relate to the various types of tracks in the application.
最后,ViewModels
项目中的 AudioTracksViewModel
在初始化时调用 TracksModel.GetAudioTracks
方法,这发生在 AudioTracksView
code> 由用户加载.AudioTracksView
左侧有一个 ListBox
,其中包含满足用户搜索和/或过滤器选择的所有 AudioTrack
对象.屏幕右侧有所选AudioTrack
的字段.这是它的样子(如果链接似乎已损坏,您可以在此处查看图像):
Finally, the AudioTracksViewModel
in the ViewModels
project calls the TracksModel.GetAudioTracks
method upon initialisation which happens when the AudioTracksView
is loaded by the user. The AudioTracksView
has a ListBox
on the left containing all of the AudioTrack
objects that meet the users search and/or filter selections. The right of the screen has the fields for the selected AudioTrack
. Here is what it looks like (if the link seems broken, you can view the image here):
右侧带有编辑 Button
的更透明字段是连接到集合的只读字段.编辑 Button
会打开一个对话框,让用户输入多个项目,然后在字段中汇总这些项目.应用程序中的所有对象都具有或多或少复杂性的相似视图.
The more transparent fields with an edit Button
on the right are read only fields connected to collections. The edit Button
opens a dialog to let the user enter multiple items, which are then summarised in the field. All of the objects in the application have similar views of more or less complexity.
这篇关于数据实体域对象ViewModels,每个都有截然不同的数据结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!