0

私のプロジェクトでは、Linq To SQL dbml ファイル、各 DB テーブルのリポジトリ レイヤー、および各リポジトリのサービス レイヤーがあります。

私のサービスでは、検証用のメタデータがいくつかあり、各 (テーブル) クラスを拡張して、オブジェクトにカスタム情報を追加します (これは以下のコードで確認できます)。

私の質問は、サービス層で拡張されたクラスを使用する代わりに、各 (テーブル) クラスのカスタム 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) 

今私が遭遇したことの 1 つは、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 オブジェクトを作成し、それらを使用してビューとやり取りすることは理にかなっています。ビューモデル オブジェクトはさまざまなモデル情報の複合体である可能性があるためです。

そうすることで、ビューモデル オブジェクトがユーザー インターフェイスに特に適していること、および通常のモデル オブジェクトでは機能しない画面固有のリストやその他のプロパティが含まれていることを確認できるという追加の利点があります。これにより、逆に利点を実現することもできます。なぜなら、ビューモデル オブジェクトは、人生の目的以外のもので雑然としたり肥大化したりする必要がないからです。(Linq to SQL オブジェクトは、状態を追跡し、UI とはまったく関係のない多くのことを実行する必要があります。)

分離は良い習慣ですが、あなたが言うように「お尻の痛み」になる可能性があります。クラス インスタンス間で情報を簡単に転送するには、Automapper を調べます。Automapperはそれを非常にうまく処理し、面倒だが必要なコードの無数の行を削除できます。

ハッピーコーディング!

于 2010-07-12T02:14:22.213 に答える