数据实体>域对象> ViewModels,每个都有完全不同的数据结构

时间:2013-10-30 20:58:50

标签: c# entity-framework architecture domain-driven-design automapper

这是关于数据实体,域对象和ViewModel之间的映射的一般性问题。我可能不会问它是正确的,但希望我能理解它。以下是一个简化的问题。

假设我有一个实体框架模型,它将1:1映射到我的数据库表,但我的域对象可能不相同,而且我的ViewModel再次完全不同。作为一个伪示例:

数据库/ EF实体:

  • MembershipAccount
  • MembershipAccountExtraInfo

域:

  • 帐户
  • 资料
  • 选择

视图模型:

  • UserProfileModel

假设我需要显示一个UserProfileModel,其中包含:用户名(来自MembershipAccount 的),SignupDate(来自MembershipAccount ),FullName(来自MembershipAccountExtraInfo的 )和TimeZone(来自MembershipAccountExtraInfo

我可能需要什么样的关系,以及什么样的映射机制?是否有类似AccountMapper的东西,它同时接受MembershipAccount和MembershipAccountExtraInfo并返回一个帐户?当需要几个对象来创建单个域实体时,我有点卡在映射上,反之亦然。

如果有帮助:我正在设计一个用于管理用户帐户,用户配置文件,用户首选项等的API,但数据库表格遍布不计。可能需要从跨越4-5个表和2个数据库的数据创建单个用户配置文件。我的数据库表和任何(逻辑)域对象之间没有1:1映射。

谢谢!

1 个答案:

答案 0 :(得分:2)

我喜欢将我的域对象保持尽可能接近它们所代表的对象。我的意思是,如果帐户具有首选项,则域Account对象应包含Preferences属性,很可能由Preference个对象的集合表示。如果不出意外,这有助于用户轻松理解应用程序的数据结构。

至于构建视图模型,这是最简单的一点......你只需要为任何需要的东西添加属性。您需要哪些类型的属性实际上取决于您如何构建域对象。

如果您的视图具有您在问题中提到的要求,并且您将域对象建模在它们所代表的对象上,那么通过它的声音,您只需要一个Account对象,因为那样其中包含PreferenceProfile个对象。

最后,需要完成的唯一“映射”可以使用实体框架使用LinQ查询完成。在这一点上,我加入表格并提取我正在处理的任何对象所需的任何数据。以下是从三个表中的数据实例化对象的示例(使用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();
}

更新>>>

扩展我的AudioTracks示例并向后工作,GetAudioTracks方法位于名为DataProviders的项目中。它是从GetAudioTracks类中的DataController方法调用的,它只是添加用户反馈和重试选项。这反过来由TracksModel项目中的Models调用,该项目仅包含DataController类中与应用程序中各种类型的轨道相关的方法的子部分。

最后,AudioTracksViewModel项目中的ViewModels在初始化时调用TracksModel.GetAudioTracks方法,该方法在用户加载AudioTracksView时发生。 AudioTracksView左侧有一个ListBox,其中包含符合用户搜索和/或过滤选择的所有AudioTrack个对象。屏幕右侧包含所选AudioTrack的字段。这是它的样子(如果链接看起来坏了,你可以查看图像here):

AudioTracksView

右侧带有编辑Button的更透明的字段是连接到集合的只读字段。编辑Button打开一个对话框,让用户输入多个项目,然后在字段中进行汇总。应用程序中的所有对象都有类似的或多或少复杂的视图。