0

在我的项目中,我有我的 Linq To SQL dbml 文件、每个数据库表的存储库层和每个存储库的服务层。

在我的服务中,我有一些用于验证的元数据,并且我扩展了每个(表)类以向对象添加一些自定义信息(您将在下面的代码中看到这一点)。

我的问题是,我应该考虑为每个(表)类构建一个自定义 ViewModal,而不是在服务层中使用扩展类吗?

下面是我现在拥有的一个例子。

存储库

Namespace Domain 
#Region "Interface" 
    Public Interface IUserRepository 
        Sub AddUser(ByVal openid As OpenID) 
        Function GetUsers() As IQueryable(Of User) 
        Sub UpdateUser(ByVal user As User) 
        Sub SubmitChanges() 
    End Interface 
#End Region 
#Region "Repository" 
    Public Class UserRepository : Implements IUserRepository 
        Private dc As MyDatabaseDataContext 
        Public Sub New() 
            dc = New MyDatabaseDataContext 
        End Sub 

        Public Sub AddUser(ByVal openid As OpenID) Implements IUserRepository.AddUser 
            Dim user As New User 
            user.MemberSince = DateTime.Now 
            openid.User = user 

            dc.OpenIDs.InsertOnSubmit(openid) 
        End Sub 

        Public Function GetUsers() As IQueryable(Of User) Implements IUserRepository.GetUsers 
            Dim users = (From u In dc.Users 
                        Select u) 
            Return users.AsQueryable 
        End Function 

        Public Sub UpdateUser(ByVal user As User) Implements IUserRepository.UpdateUser 
            Dim _user = (From u In dc.Users 
                Where u.ID = user.ID 
                Select u).Single 

            With _user 
                .About = user.About 
                .BirthDate = user.BirthDate 
                .Email = user.Email 
                .isClosed = user.isClosed 
                .isProfileComplete = user.isProfileComplete 
                .RegionID = user.RegionID 
                .Reputation = user.Reputation 
                .UserName = user.UserName 
                .WebSite = user.WebSite 
            End With 

        End Sub 

        Public Sub SubmitChanges() Implements IUserRepository.SubmitChanges 
            dc.SubmitChanges() 
        End Sub 
    End Class 
#End Region 
End Namespace 

服务

Imports System.ComponentModel.DataAnnotations 

Namespace Domain 
#Region "Validation" 
    <MetadataType(GetType(UserMetaData))> _ 
    Partial Public Class User 
        Public Property UserRegion As String 
        Public Property LastSeen As DateTime 
        Public ReadOnly Property Slug(ByVal user As User) As String
           Get
              Return Replace(user.UserName, " ", "-")
           End Get
        End Property
    End Class 


    ''' <summary> 
    ''' Validation for all User data. 
    ''' </summary> 
    ''' <remarks>All validation is done at the Service Layer</remarks> 
    Public Class UserMetaData 

        <DisplayName("name")> _ 
        <Required(ErrorMessage:="Username is required.")> _ 
        <StringLength(30, ErrorMessage:="Username cannot exceed 30 characters.")> _ 
        <RegularExpression("^\w{3,30}$", ErrorMessage:="Not a valid username.")> _ 
        Public Property UserName As String 

        <DisplayName("email")> _ 
        <StringLength(50, ErrorMessage:="Email Address cannot exceed 50 characters.")> _ 
        <RegularExpression("^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})$", ErrorMessage:="Not a valid email address.")> _ 
        Public Property Email As String 

        <DisplayName("website")> _ 
        <StringLength(256, ErrorMessage:="Web Address cannot exceed 256 characters.")> _ 
        <RegularExpression("^http(s?)\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$", ErrorMessage:="Not a valid website address.")> _ 
        Public Property WebSite As String 

        <DisplayName("about")> _ 
        <StringLength(2000, ErrorMessage:="Profile cannot exceed 2000 characters.")> _ 
        Public Property About As String 

        <DisplayName("region")> _ 
        <Required(ErrorMessage:="Region is required.")> _ 
        Public Property UserRegion As Integer 

        <DisplayName("birthdate")> _ 
        <DisplayFormat(ApplyFormatInEditMode:=True, ConvertEmptyStringToNull:=True, DataFormatString:="{0:MM/dd/yyyy}")> _ 
        Public Property BirthDate As DateTime 

    End Class 
#End Region 
#Region "Interface" 
    Public Interface IUserService 
        Sub AddUser(ByVal claimedidentifier As String, ByVal notes As String) 
        Function GetAllUsers() As IList(Of User) 
        Function GetUserByID(ByVal id As Integer) As User 
        Sub UpdateUser(ByVal user As User) 
        Sub SubmitChanges() 
    End Interface 
#End Region 
#Region "Service" 
    Public Class UserService : Implements IUserService 
        Private _UserRepository As IUserRepository 
        Public Sub New(ByVal UserRepository As IUserRepository) 
            _UserRepository = UserRepository 
        End Sub 

        Public Sub AddUser(ByVal claimedidentifier As String, ByVal notes As String) Implements IUserService.AddUser 
            Dim openid As New OpenID 
            openid.ClaimedIdentifier = claimedidentifier 
            openid.UserNotes = notes 
            _UserRepository.AddUser(openid) 
        End Sub 

        Public Function GetAllUsers() As System.Collections.Generic.IList(Of User) Implements IUserService.GetAllUsers 
            Return _UserRepository.GetUsers().Where(Function(u) (Not u.isClosed)).ToList 
        End Function 

        Public Function GetUserByID(ByVal id As Integer) As User Implements IUserService.GetUserByID 
            Return _UserRepository.GetUsers().Where(Function(u) (Not u.isClosed And u.ID = id)).SingleOrDefault 
        End Function 

        Public Sub UpdateUser(ByVal user As User) Implements IUserService.UpdateUser 
            _UserRepository.UpdateUser(user) 
        End Sub 

        Public Sub SubmitChanges() Implements IUserService.SubmitChanges 
            _UserRepository.SubmitChanges() 
        End Sub 

    End Class 
#End Region 

End Namespace 

目前在我的控制器中,我像这样将模态数据发送到我的视图

    Dim user As Domain.User = UserService.GetUserByID(id) 
    Return View(user) 

现在我遇到的一件事是每当我需要使用 Slug 时都需要将用户对象发送到 Slug 属性

    Dim user As Domain.User = UserService.GetUserByID(id) 
    user.Slug = user.Slug(user)  ''# this seems like a bit of a pain in the ass
    Return View(user) 

所以正因为如此,为每个(表)类创建一个自定义 ViewModal 并简单地执行以下操作对我来说更好吗

    Dim user As Domain.UserViewModal = New Domain.UserViewModal(UserService.GetUserByID(id))
    ''# The UserViewModal will automatically do all the work to create the 
    ''# Slug as well as other pertinent information
    Return View(user) 

在我看来,分离是一件好事,但仍然需要大量的时间来构建。只是想知道权衡的好处,或者是否有更好的方法来完成同样的事情?

4

1 回答 1

1

您可能会发现您的模型类并不总是与视图 1:1 对应。仅出于这个原因,创建 ViewModel 对象并使用它们与您的视图交互是有意义的,因为 viewmodel 对象可以是各种模型信息的组合。

这样做还有一个额外的好处,即确保您的视图模型对象特别适合用户界面,并且可能包含特定于屏幕的列表或其他与普通模型对象无关的属性。这使您也可以反过来实现收益,因为您的视图模型对象不需要被任何东西弄得杂乱/臃肿,除了它们在生活中的目的。(Linq to SQL 对象必须跟踪状态并完成大量与 UI 完全无关的事情。)

虽然分离是一种很好的做法,但正如你所说的那样,它可能是“屁股痛”。为了让您的类实例之间的信息传输更容易,请查看Automapper,它做得非常好,并允许您消除无数行繁琐但必要的代码。

快乐编码!

于 2010-07-12T02:14:22.213 回答