Membuat Objek Transfer Data (DTO)
Saat ini, API web kami mengekspos entitas database kepada klien. Klien menerima data yang memetakan langsung ke tabel database Anda. Namun, itu tidak selalu ide yang baik. Terkadang Anda ingin mengubah bentuk data yang Anda kirim ke klien. Misalnya, Anda mungkin perlu:
- Hapus referensi melingkar (lihat bagian sebelumnya).
- Sembunyikan properti tertentu yang tidak seharusnya dilihat klien.
- Hilangkan beberapa properti untuk mengurangi ukuran payload.
- Meratakan grafik objek yang berisi objek berlapis, untuk membuatnya lebih nyaman bagi klien.
- Hindari kerentanan "posting berlebihan". (Lihat Validasi Model untuk diskusi tentang posting berlebihan.)
- Memisahkan lapisan layanan Anda dari lapisan database Anda.
Untuk mencapai hal ini, Anda dapat menentukan objek transfer data (DTO). DTO adalah objek yang menentukan bagaimana data akan dikirim melalui jaringan. Mari kita lihat cara kerjanya dengan entitas Buku. Di folder Model, tambahkan dua kelas DTO:
namespace BookService.Models
{
public class BookDto
{
public int Id { get; set; }
public string Title { get; set; }
public string AuthorName { get; set; }
}
}
namespace BookService.Models
{
public class BookDetailDto
{
public int Id { get; set; }
public string Title { get; set; }
public int Year { get; set; }
public decimal Price { get; set; }
public string AuthorName { get; set; }
public string Genre { get; set; }
}
}
Kelas BookDetailDto
mencakup semua properti dari model Buku, kecuali itu AuthorName
adalah string yang akan menyimpan nama pembuat. Kelas BookDto
berisi subset properti dari BookDetailDto
.
Selanjutnya, ganti dua metode GET di BooksController
kelas , dengan versi yang mengembalikan DTO. Kita akan menggunakan pernyataan LINQ Select untuk mengonversi dari entitas Buku menjadi DTO.
// GET api/Books
public IQueryable<BookDto> GetBooks()
{
var books = from b in db.Books
select new BookDto()
{
Id = b.Id,
Title = b.Title,
AuthorName = b.Author.Name
};
return books;
}
// GET api/Books/5
[ResponseType(typeof(BookDetailDto))]
public async Task<IHttpActionResult> GetBook(int id)
{
var book = await db.Books.Include(b => b.Author).Select(b =>
new BookDetailDto()
{
Id = b.Id,
Title = b.Title,
Year = b.Year,
Price = b.Price,
AuthorName = b.Author.Name,
Genre = b.Genre
}).SingleOrDefaultAsync(b => b.Id == id);
if (book == null)
{
return NotFound();
}
return Ok(book);
}
Berikut adalah SQL yang dihasilkan oleh metode baru GetBooks
. Anda dapat melihat bahwa EF menerjemahkan LINQ Select ke dalam pernyataan SQL SELECT.
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Title] AS [Title],
[Extent2].[Name] AS [Name]
FROM [dbo].[Books] AS [Extent1]
INNER JOIN [dbo].[Authors] AS [Extent2] ON [Extent1].[AuthorId] = [Extent2].[Id]
Terakhir, ubah PostBook
metode untuk mengembalikan DTO.
[ResponseType(typeof(BookDto))]
public async Task<IHttpActionResult> PostBook(Book book)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Books.Add(book);
await db.SaveChangesAsync();
// New code:
// Load author name
db.Entry(book).Reference(x => x.Author).Load();
var dto = new BookDto()
{
Id = book.Id,
Title = book.Title,
AuthorName = book.Author.Name
};
return CreatedAtRoute("DefaultApi", new { id = book.Id }, dto);
}
Catatan
Dalam tutorial ini, kita mengonversi ke DTO secara manual dalam kode. Opsi lain adalah menggunakan pustaka seperti AutoMapper yang menangani konversi secara otomatis.
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk