8

tôi đã mô hình miền sau:DTO có thể có DTO lồng nhau không?

public class Playlist 
{ 
    public long Id { get; set; } 
    public string Title { get; set; } 
    public virtual ICollection<Song> Songs { get; set; } 
} 

public class Song 
{ 
    public long Id { get; set; } 
    public string Name { get; set; } 
    public virtual Playlist Playlist { get; set; } 
    public virtual ICollection<Catalog> Matches { get; set; } 
} 

public class Catalog 
{ 
    public long Id { get; set; } 
    public string Title { get; set; } 
} 

dịch vụ của tôi có đoạn mã sau:

public PlaylistResult FindByPlaylistId(long id) 
{ 
    Playlist playlist = playlistRepository.GetById(id); 

    foreach (var song in playlist.Songs) 
    { 
     song.Matches = catalogRepository.GetMatches(song.Name).ToList(); 
    } 

    return new PlaylistResult(new PlaylistDTO(playlist), playlist.Songs.Select(x => new SongDTO(x))); 
} 

dịch vụ của tôi được một danh sách nhạc và các bài hát từ các cơ sở dữ liệu và sau đó cho mỗi bài hát trong danh sách nhạc nó cháy một truy vấn để nhận thêm các kết quả phù hợp từ cơ sở dữ liệu (sử dụng tìm kiếm toàn văn SQL Server) cụ thể cho bài hát đó.

Dữ liệu sau đó được chuyển đổi thành DTO, được thêm vào đối tượng kết quả và được truyền lại cho bộ điều khiển. Mã này trông giống như:

public class PlaylistResult 
{ 
    public PlaylistResult(PlaylistDTO playlist, IEnumerable<SongDTO> songs) 
    { 
     Playlist = playlist; 
     Songs = songs; 
    } 

    public PlaylistDTO Playlist { get; private set; } 

    public IEnumerable<SongDTO> Songs { get; private set; } 
} 

Vấn đề:

Đối tượng PlaylistResult đã làm việc rất lớn cho đến nay nhưng việc giới thiệu gần đây của trận đấu đã làm cho mọi việc phức tạp hơn một chút. Dường như tôi không có lựa chọn nào khác ngoài việc sửa đổi SongDTO tôi phải đưa vào tài khoản các trận đấu và tìm kiếm như thế này:

public class SongDTO 
{ 
    public SongDTO(Song song, IEnumerable<CatalogDTO> matches) 
    { 
     Id = song.Id; 
     Name = song.Name; 
     Matches = matches; 
    } 

    public long Id { get; private set; } 

    public string Name { get; private set; } 

    public IEnumerable<CatalogDTO> Matches { get; private set; } 
} 

Nhưng không này vi phạm các mục đích của DTO của? Đó là sự hiểu biết của tôi rằng DTOs là một đại diện phẳng của dữ liệu và cách tiếp cận này không phải là phẳng. Mặt khác, tôi không thấy cách khác để làm điều này vì mỗi trận đấu là đặc trưng cho mỗi bài hát.

Tôi biết rằng tôi có thể làm cho điều này dễ dàng hơn trên bản thân mình và ném ra DTO và chuyển mô hình miền trực tiếp đến bộ điều khiển và gọi nó là một ngày. Nhưng tôi không muốn làm điều đó vì toàn bộ mục đích là học cách làm việc với DTO.

Bất kỳ đầu vào nào được đánh giá cao.

+0

Lưu ý rằng bạn có thể đang tạo mô hình miền thiếu máu. Các đối tượng miền của bạn dường như không để lộ bất kỳ hành vi nào - nó chỉ là các getters và setters công khai (rất nguy hiểm). – hoetz

+0

Tôi giữ nó đơn giản vì lợi ích của ví dụ. – Thomas

Trả lời

8

DTO không phải là biểu diễn dữ liệu dạng phẳng mặc dù chúng có thể.

Đó là vẻ đẹp của chúng - bạn có thể cấu trúc chúng như bạn cần, trái ngược với cách cơ sở dữ liệu định nghĩa mọi thứ. Ngoài ra họ là một phương tiện tách dữ liệu khỏi hành vi.

Tôi sẽ không đặt tham chiếu đến đối tượng Miền trong DTO. (Bạn có nó trong constructor) Sử dụng một nhà máy để xây dựng của DTO để khách hàng của bạn chỉ cần tham khảo của DTO và không phải là các đối tượng miền.

Song mySong; 
SongDTO = DTOFactory.GetSong(mySong); 

Nếu khách hàng của bạn cần tham khảo các đối tượng Miền thì họ cũng có thể sử dụng chúng!

+0

Cảm ơn. Vì vậy, nói cách khác, làm tổ DTO là một cách tiếp cận chấp nhận được? – Thomas

+2

Tuyệt đối - không trộn lẫn và kết hợp DTO với đối tượng miền! – BonyT

0

Điều bạn đã làm là chính xác. Tôi nghĩ rằng chúng chủ yếu là biểu diễn phẳng khi bạn chuyển dữ liệu đến/từ lớp dữ liệu của ứng dụng của bạn.

Các vấn đề liên quan