Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
oleh Tom Dykstra
Seri tutorial ini dibangun pada aplikasi web Contoso University yang dibuat oleh seri tutorial Memulai Entity Framework 4.0 . Jika Anda tidak menyelesaikan tutorial sebelumnya, sebagai titik awal untuk tutorial ini, Anda dapat mengunduh aplikasi yang akan Anda buat. Anda juga dapat mengunduh aplikasi yang dibuat oleh seri tutorial lengkap. Jika Anda memiliki pertanyaan tentang tutorial, Anda dapat mempostingnya ke forum ASP.NET Entity Framework.
Dalam tutorial sebelumnya, Anda melihat cara menangani konflik konkurensi. Tutorial ini menunjukkan opsi untuk meningkatkan performa aplikasi web ASP.NET yang menggunakan Kerangka Kerja Entitas. Anda akan mempelajari beberapa metode untuk memaksimalkan performa atau untuk mendiagnosis masalah performa.
Informasi yang disajikan di bagian berikut kemungkinan akan berguna dalam berbagai skenario:
- Memuat data terkait secara efisien.
- Kelola status tampilan.
Informasi yang disajikan di bagian berikut mungkin berguna jika Anda memiliki kueri individual yang menyajikan masalah performa:
-
NoTracking
Gunakan opsi gabungkan. - Pra-kompilasi kueri LINQ.
- Periksa perintah kueri yang dikirim ke database.
Informasi yang disajikan di bagian berikut berpotensi berguna untuk aplikasi yang memiliki model data yang sangat besar:
- Tampilan pra-hasil.
Catatan
Performa aplikasi web dipengaruhi oleh banyak faktor, termasuk hal-hal seperti ukuran data permintaan dan respons, kecepatan kueri database, berapa banyak permintaan yang dapat diantrekan server dan seberapa cepat dapat melayaninya, dan bahkan efisiensi pustaka skrip klien apa pun yang mungkin Anda gunakan. Jika performa sangat penting dalam aplikasi Anda, atau jika pengujian atau pengalaman menunjukkan bahwa performa aplikasi tidak memuaskan, Anda harus mengikuti protokol normal untuk penyetelan performa. Ukur untuk menentukan di mana penyempitan performa terjadi, lalu atasi area yang akan berdampak terbesar pada performa aplikasi secara keseluruhan.
Topik ini berfokus terutama pada cara-cara di mana Anda dapat berpotensi meningkatkan performa khusus dari Kerangka Kerja Entitas di ASP.NET. Saran di sini berguna jika Anda menentukan bahwa akses data adalah salah satu hambatan performa dalam aplikasi Anda. Kecuali seperti yang disebutkan, metode yang dijelaskan di sini tidak boleh dianggap sebagai "praktik terbaik" secara umum - banyak dari mereka hanya sesuai dalam situasi yang luar biasa atau untuk mengatasi jenis penyempitan performa yang sangat spesifik.
Untuk memulai tutorial, mulai Visual Studio dan buka aplikasi web Contoso University yang sedang Anda kerjakan di tutorial sebelumnya.
Memuat Data Terkait secara Efisien
Ada beberapa cara agar Kerangka Kerja Entitas dapat memuat data terkait ke dalam properti navigasi entitas:
Pemuatan malas. Saat entitas pertama kali dibaca, data terkait tidak diambil. Namun, pertama kali Anda mencoba mengakses properti navigasi, data yang diperlukan untuk properti navigasi tersebut diambil secara otomatis. Ini menghasilkan beberapa kueri yang dikirim ke database — satu untuk entitas itu sendiri dan satu setiap kali data terkait untuk entitas harus diambil.
Pemuatan bersemangat. Saat entitas dibaca, data terkait diambil bersama dengan entitas tersebut. Ini biasanya menghasilkan satu kueri gabungan yang mengambil semua data yang diperlukan. Anda menentukan pemuatan bersemangat dengan menggunakan Include
metode , seperti yang telah Anda lihat dalam tutorial ini.
Pemuatan eksplisit. Ini mirip dengan pemuatan malas, kecuali bahwa Anda secara eksplisit mengambil data terkait dalam kode; itu tidak terjadi secara otomatis saat Anda mengakses properti navigasi. Anda memuat data terkait secara manual menggunakan
Load
metode properti navigasi untuk koleksi, atau Anda menggunakanLoad
metode properti referensi untuk properti yang menyimpan satu objek. (Misalnya, Anda memanggilPersonReference.Load
metode untuk memuatPerson
propertiDepartment
navigasi entitas.)
Karena tidak segera mengambil nilai properti, pemuatan malas dan pemuatan eksplisit juga keduanya dikenal sebagai pemuatan yang ditangguhkan.
Pemuatan malas adalah perilaku default untuk konteks objek yang telah dihasilkan oleh perancang. Jika Anda membuka SchoolModel.Designer. file cs yang menentukan kelas konteks objek, Anda akan menemukan tiga metode konstruktor, dan masing-masing mencakup pernyataan berikut:
this.ContextOptions.LazyLoadingEnabled = true;
Secara umum, jika Anda tahu Bahwa Anda memerlukan data terkait untuk setiap entitas yang diambil, pemuatan bersemangat menawarkan performa terbaik, karena satu kueri yang dikirim ke database biasanya lebih efisien daripada kueri terpisah untuk setiap entitas yang diambil. Di sisi lain, jika Anda perlu mengakses properti navigasi entitas hanya jarang atau hanya untuk sekumpulan kecil entitas, pemuatan malas atau pemuatan eksplisit mungkin lebih efisien, karena pemuatan yang bersemangat akan mengambil lebih banyak data daripada yang Anda butuhkan.
Dalam aplikasi web, pemuatan malas mungkin memiliki nilai yang relatif sedikit, karena tindakan pengguna yang memengaruhi kebutuhan akan data terkait terjadi di browser, yang tidak memiliki koneksi ke konteks objek yang merender halaman. Di sisi lain, ketika Anda menggabungkan data kontrol, Anda biasanya tahu data apa yang Anda butuhkan, sehingga umumnya yang terbaik adalah memilih pemuatan yang bersemangat atau pemuatan yang ditangguhkan berdasarkan apa yang sesuai dalam setiap skenario.
Selain itu, kontrol terikat data mungkin menggunakan objek entitas setelah konteks objek dibuang. Dalam hal ini, upaya untuk malas memuat properti navigasi akan gagal. Pesan kesalahan yang Anda terima jelas: "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
"
EntityDataSource
Kontrol menonaktifkan pemuatan malas secara default.
ObjectDataSource
Untuk kontrol yang Anda gunakan untuk tutorial saat ini (atau jika Anda mengakses konteks objek dari kode halaman), ada beberapa cara Anda dapat membuat pemuatan malas dinonaktifkan secara default. Anda dapat menonaktifkannya saat membuat instans konteks objek. Misalnya, Anda dapat menambahkan baris berikut ke metode SchoolRepository
konstruktor kelas :
context.ContextOptions.LazyLoadingEnabled = false;
Untuk aplikasi Contoso University, Anda akan membuat konteks objek secara otomatis menonaktifkan pemuatan malas sehingga properti ini tidak harus diatur setiap kali konteks dibuat.
Buka model data SchoolModel.edmx , klik permukaan desain, lalu di panel properti atur properti Lazy Loading Enabled ke False
. Simpan dan tutup model data.
Mengelola Status Tampilan
Untuk menyediakan fungsionalitas pembaruan, halaman web ASP.NET harus menyimpan nilai properti asli entitas saat halaman dirender. Selama pemrosesan postback, kontrol dapat membuat ulang status asli entitas dan memanggil metode entitas Attach
sebelum menerapkan perubahan dan memanggil SaveChanges
metode . Secara default, kontrol data ASP.NET Web Forms menggunakan status tampilan untuk menyimpan nilai asli. Namun, status tampilan dapat memengaruhi performa, karena disimpan di bidang tersembunyi yang secara substansial dapat meningkatkan ukuran halaman yang dikirim ke dan dari browser.
Teknik untuk mengelola status tampilan, atau alternatif seperti status sesi, tidak unik untuk Kerangka Kerja Entitas, sehingga tutorial ini tidak masuk ke topik ini secara rinci. Untuk informasi selengkapnya, lihat tautan di akhir tutorial.
Namun, versi 4 ASP.NET menyediakan cara baru untuk bekerja dengan status tampilan yang harus diperhatikan oleh setiap pengembang ASP.NET aplikasi Web Forms: ViewStateMode
properti . Properti baru ini dapat diatur di tingkat halaman atau kontrol, dan memungkinkan Anda menonaktifkan status tampilan secara default untuk halaman dan mengaktifkannya hanya untuk kontrol yang membutuhkannya.
Untuk aplikasi di mana performa sangat penting, praktik yang baik adalah selalu menonaktifkan status tampilan di tingkat halaman dan mengaktifkannya hanya untuk kontrol yang memerlukannya. Ukuran status tampilan di halaman Contoso University tidak akan dikurangi secara substansial oleh metode ini, tetapi untuk melihat cara kerjanya, Anda akan melakukannya untuk halaman Instruktur.aspx . Halaman tersebut berisi banyak kontrol, termasuk Label
kontrol yang status tampilannya dinonaktifkan. Tidak ada kontrol pada halaman ini yang benar-benar perlu mengaktifkan status tampilan.
DataKeyNames
(Properti GridView
kontrol menentukan status yang harus dipertahankan di antara postback, tetapi nilai-nilai ini disimpan dalam status kontrol, yang tidak terpengaruh oleh ViewStateMode
properti.)
Markup Page
direktif dan Label
kontrol saat ini menyerupai contoh berikut:
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"
CodeBehind="Instructors.aspx.cs" Inherits="ContosoUniversity.Instructors" %>
...
<asp:Label ID="ErrorMessageLabel" runat="server" Text="" Visible="false" ViewStateMode="Disabled"></asp:Label>
...
Buat perubahan berikut:
- Tambahkan
ViewStateMode="Disabled"
ke direktifPage
. - Hapus
ViewStateMode="Disabled"
dariLabel
kontrol.
Markup sekarang menyerupai contoh berikut:
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"
CodeBehind="Instructors.aspx.cs" Inherits="ContosoUniversity.Instructors"
ViewStateMode="Disabled" %>
...
<asp:Label ID="ErrorMessageLabel" runat="server" Text="" Visible="false"></asp:Label>
...
Status tampilan sekarang dinonaktifkan untuk semua kontrol. Jika nanti Anda menambahkan kontrol yang memang perlu menggunakan status tampilan, yang perlu Anda lakukan adalah menyertakan atribut untuk kontrol tersebut ViewStateMode="Enabled"
.
Menggunakan opsi penggabungan NoTracking
Saat konteks objek mengambil baris database dan membuat objek entitas yang mewakilinya, secara default konteks tersebut juga melacak objek entitas tersebut menggunakan manajer status objeknya. Data pelacakan ini bertindak sebagai cache dan digunakan saat Anda memperbarui entitas. Karena aplikasi web biasanya memiliki instans konteks objek berumur pendek, kueri sering mengembalikan data yang tidak perlu dilacak, karena konteks objek yang membacanya akan dibuang sebelum salah satu entitas yang dibacanya digunakan lagi atau diperbarui.
Dalam Kerangka Kerja Entitas, Anda dapat menentukan apakah konteks objek melacak objek entitas dengan mengatur opsi penggabungan. Anda dapat mengatur opsi penggabungan untuk kueri individual atau untuk set entitas. Jika Anda mengaturnya untuk kumpulan entitas, itu berarti Anda mengatur opsi penggabungan default untuk semua kueri yang dibuat untuk kumpulan entitas tersebut.
Untuk aplikasi Contoso University, pelacakan tidak diperlukan untuk salah satu set entitas yang Anda akses dari repositori, sehingga Anda dapat mengatur opsi penggabungan ke NoTracking
untuk kumpulan entitas tersebut saat Anda membuat instans konteks objek di kelas repositori. (Perhatikan bahwa dalam tutorial ini, mengatur opsi penggabungan tidak akan memiliki efek nyata pada performa aplikasi. Opsi NoTracking
ini kemungkinan akan membuat peningkatan performa yang dapat diamati hanya dalam skenario volume data tinggi tertentu.)
Di folder DAL, buka file SchoolRepository.cs dan tambahkan metode konstruktor yang mengatur opsi penggabungan untuk kumpulan entitas yang diakses repositori:
public SchoolRepository()
{
context.Departments.MergeOption = MergeOption.NoTracking;
context.InstructorNames.MergeOption = MergeOption.NoTracking;
context.OfficeAssignments.MergeOption = MergeOption.NoTracking;
}
Pra-Kompilasi Kueri LINQ
Pertama kali Kerangka Kerja Entitas menjalankan kueri SQL Entitas dalam masa pakai instans tertentu ObjectContext
, dibutuhkan beberapa waktu untuk mengkompilasi kueri. Hasil kompilasi di-cache, yang berarti bahwa eksekusi kueri berikutnya jauh lebih cepat. Kueri LINQ mengikuti pola yang sama, kecuali bahwa beberapa pekerjaan yang diperlukan untuk mengkompilasi kueri dilakukan setiap kali kueri dijalankan. Dengan kata lain, untuk kueri LINQ, secara default tidak semua hasil kompilasi di-cache.
Jika Anda memiliki kueri LINQ yang Anda harapkan berjalan berulang kali dalam masa pakai konteks objek, Anda dapat menulis kode yang menyebabkan semua hasil kompilasi di-cache saat pertama kali kueri LINQ dijalankan.
Sebagai ilustrasi, Anda akan melakukan ini untuk dua Get
metode di SchoolRepository
kelas , salah satunya tidak mengambil parameter apa pun ( GetInstructorNames
metode ), dan yang memang memerlukan parameter ( GetDepartmentsByAdministrator
metode ). Metode ini karena mereka berdiri sekarang sebenarnya tidak perlu dikompilasi karena mereka bukan kueri LINQ:
public IEnumerable<InstructorName> GetInstructorNames()
{
return context.InstructorNames.OrderBy("it.FullName").ToList();
}
public IEnumerable<Department> GetDepartmentsByAdministrator(Int32 administrator)
{
return new ObjectQuery<Department>("SELECT VALUE d FROM Departments as d", context, MergeOption.NoTracking).Include("Person").Where(d => d.Administrator == administrator).ToList();
}
Namun, sehingga Anda dapat mencoba kueri yang dikompilasi, Anda akan melanjutkan seolah-olah ini telah ditulis sebagai kueri LINQ berikut:
public IEnumerable<InstructorName> GetInstructorNames()
{
return (from i in context.InstructorNames orderby i.FullName select i).ToList();
}
public IEnumerable<Department> GetDepartmentsByAdministrator(Int32 administrator)
{
context.Departments.MergeOption = MergeOption.NoTracking;
return (from d in context.Departments where d.Administrator == administrator select d).ToList();
}
Anda dapat mengubah kode dalam metode ini ke apa yang ditunjukkan di atas dan menjalankan aplikasi untuk memverifikasi bahwa kode berfungsi sebelum melanjutkan. Tetapi instruksi berikut langsung masuk ke dalam membuat versi yang telah dikompilasi sebelumnya.
Buat file kelas di folder DAL , beri nama SchoolEntities.cs, dan ganti kode yang ada dengan kode berikut:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Objects;
namespace ContosoUniversity.DAL
{
public partial class SchoolEntities
{
private static readonly Func<SchoolEntities, IQueryable<InstructorName>> compiledInstructorNamesQuery =
CompiledQuery.Compile((SchoolEntities context) => from i in context.InstructorNames orderby i.FullName select i);
public IEnumerable<InstructorName> CompiledInstructorNamesQuery()
{
return compiledInstructorNamesQuery(this).ToList();
}
private static readonly Func<SchoolEntities, Int32, IQueryable<Department>> compiledDepartmentsByAdministratorQuery =
CompiledQuery.Compile((SchoolEntities context, Int32 administrator) => from d in context.Departments.Include("Person") where d.Administrator == administrator select d);
public IEnumerable<Department> CompiledDepartmentsByAdministratorQuery(Int32 administrator)
{
return compiledDepartmentsByAdministratorQuery(this, administrator).ToList();
}
}
}
Kode ini membuat kelas parsial yang memperluas kelas konteks objek yang dihasilkan secara otomatis. Kelas parsial mencakup dua kueri LINQ yang dikompilasi menggunakan Compile
metode CompiledQuery
kelas . Ini juga membuat metode yang dapat Anda gunakan untuk memanggil kueri. Simpan dan tutup file ini.
Selanjutnya, di SchoolRepository.cs, ubah metode dan GetDepartmentsByAdministrator
yang ada GetInstructorNames
di kelas repositori sehingga mereka memanggil kueri yang dikompilasi:
public IEnumerable<InstructorName> GetInstructorNames()
{
return context.CompiledInstructorNamesQuery();
}
public IEnumerable<Department> GetDepartmentsByAdministrator(Int32 administrator)
{
return context.CompiledDepartmentsByAdministratorQuery(administrator);
}
Jalankan halaman Departments.aspx untuk memverifikasi bahwa itu berfungsi seperti sebelumnya. Metode GetInstructorNames
ini dipanggil untuk mengisi daftar drop-down administrator, dan GetDepartmentsByAdministrator
metode dipanggil ketika Anda mengklik Perbarui untuk memverifikasi bahwa tidak ada instruktur yang merupakan administrator dari lebih dari satu departemen.
Anda telah mengkompilasi kueri sebelumnya di aplikasi Contoso University hanya untuk melihat cara melakukannya, bukan karena itu akan meningkatkan performa secara terukur. Kueri LINQ prakompilasi memang menambahkan tingkat kompleksitas ke kode Anda, jadi pastikan Anda melakukannya hanya untuk kueri yang benar-benar mewakili penyempitan performa dalam aplikasi Anda.
Memeriksa Kueri yang Dikirim ke Database
Saat Anda menyelidiki masalah performa, terkadang sangat membantu untuk mengetahui perintah SQL yang tepat yang dikirim kerangka kerja entitas ke database. Jika Anda bekerja dengan objek, salah satu cara untuk melakukan ini adalah dengan IQueryable
menggunakan metode .ToTraceString
Di SchoolRepository.cs, ubah kode dalam GetDepartmentsByName
metode agar sesuai dengan contoh berikut:
public IEnumerable<Department> GetDepartmentsByName(string sortExpression, string nameSearchString)
{
...
var departments = new ObjectQuery<Department>("SELECT VALUE d FROM Departments AS d", context).OrderBy("it." + sortExpression).Include("Person").Include("Courses").Where(d => d.Name.Contains(nameSearchString));
string commandText = ((ObjectQuery)departments).ToTraceString();
return departments.ToList();
}
Variabel departments
harus ditransmisikan ke ObjectQuery
jenis hanya karena Where
metode di akhir baris sebelumnya membuat IQueryable
objek; tanpa Where
metode , transmisi tidak akan diperlukan.
Atur titik henti pada return
baris, lalu jalankan halaman Departments.aspx di debugger. Saat Anda menekan titik henti, periksa commandText
variabel di jendela Lokal dan gunakan visualizer teks (kaca pembesar di kolom Nilai ) untuk menampilkan nilainya di jendela Visualizer Teks . Anda dapat melihat seluruh perintah SQL yang dihasilkan dari kode ini:
Sebagai alternatif, fitur IntelliTrace di Visual Studio Ultimate menyediakan cara untuk melihat perintah SQL yang dihasilkan oleh Kerangka Kerja Entitas yang tidak mengharuskan Anda mengubah kode atau bahkan mengatur titik henti.
Catatan
Anda dapat melakukan prosedur berikut hanya jika Anda memiliki Visual Studio Ultimate.
Pulihkan kode asli dalam GetDepartmentsByName
metode , lalu jalankan halaman Departments.aspx di debugger.
Di Visual Studio, pilih menu Debug , lalu IntelliTrace, lalu Peristiwa IntelliTrace.
Di jendela IntelliTrace , klik Hentian Semua.
Jendela IntelliTrace menampilkan daftar peristiwa terbaru:
Klik baris ADO.NET . Ini diperluas untuk menunjukkan teks perintah:
Anda dapat menyalin seluruh string teks perintah ke clipboard dari jendela Lokal .
Misalkan Anda bekerja dengan database dengan lebih banyak tabel, hubungan, dan kolom daripada database sederhana School
. Anda mungkin menemukan bahwa kueri yang mengumpulkan semua informasi yang Anda butuhkan dalam satu Select
pernyataan yang berisi beberapa Join
klausa menjadi terlalu kompleks untuk bekerja secara efisien. Dalam hal ini Anda dapat beralih dari pemuatan yang bersemangat ke pemuatan eksplisit untuk menyederhanakan kueri.
Misalnya, coba ubah kode dalam GetDepartmentsByName
metode di SchoolRepository.cs. Saat ini dalam metode tersebut Anda memiliki kueri objek yang memiliki Include
metode untuk Person
properti navigasi dan Courses
.
return
Ganti pernyataan dengan kode yang melakukan pemuatan eksplisit, seperti yang ditunjukkan dalam contoh berikut:
public IEnumerable<Department> GetDepartmentsByName(string sortExpression, string nameSearchString)
{
...
var departments = new ObjectQuery<Department>("SELECT VALUE d FROM Departments AS d", context).OrderBy("it." + sortExpression).Where(d => d.Name.Contains(nameSearchString)).ToList();
foreach (Department d in departments)
{
d.Courses.Load();
d.PersonReference.Load();
}
return departments;
}
Jalankan halaman Departments.aspx di debugger dan periksa lagi jendela IntelliTrace seperti yang Anda lakukan sebelumnya. Sekarang, di mana ada satu kueri sebelumnya, Anda melihat urutan panjangnya.
Klik baris ADO.NET pertama untuk melihat apa yang telah terjadi pada kueri kompleks yang Anda lihat sebelumnya.
Kueri dari Departemen telah menjadi kueri sederhana Select
tanpa Join
klausa, tetapi diikuti oleh kueri terpisah yang mengambil kursus terkait dan administrator, menggunakan sekumpulan dua kueri untuk setiap departemen yang dikembalikan oleh kueri asli.
Catatan
Jika Anda membiarkan pemuatan malas diaktifkan, pola yang Anda lihat di sini, dengan kueri yang sama berulang kali, mungkin disebabkan oleh pemuatan malas. Pola yang biasanya ingin Anda hindari adalah data terkait pemuatan malas untuk setiap baris tabel utama. Kecuali Anda telah memverifikasi bahwa satu kueri gabungan terlalu kompleks agar efisien, Anda biasanya dapat meningkatkan performa dalam kasus seperti itu dengan mengubah kueri utama untuk menggunakan pemuatan yang bersemangat.
Tampilan Pra-Pembuatan
ObjectContext
Saat objek pertama kali dibuat di domain aplikasi baru, Kerangka Kerja Entitas menghasilkan sekumpulan kelas yang digunakannya untuk mengakses database. Kelas-kelas ini disebut tampilan, dan jika Anda memiliki model data yang sangat besar, menghasilkan tampilan ini dapat menunda respons situs web ke permintaan pertama untuk halaman setelah domain aplikasi baru diinisialisasi. Anda dapat mengurangi penundaan permintaan pertama ini dengan membuat tampilan pada waktu kompilasi daripada pada durasi.
Catatan
Jika aplikasi Anda tidak memiliki model data yang sangat besar, atau jika memiliki model data besar tetapi Anda tidak khawatir tentang masalah performa yang hanya memengaruhi permintaan halaman pertama setelah IIS didaur ulang, Anda dapat melewati bagian ini. Pembuatan tampilan tidak terjadi setiap kali Anda membuat instans ObjectContext
objek, karena tampilan di-cache di domain aplikasi. Oleh karena itu, kecuali Anda sering mendaur ulang aplikasi Anda di IIS, sangat sedikit permintaan halaman yang akan mendapat manfaat dari tampilan yang telah dibuat sebelumnya.
Anda dapat membuat tampilan terlebih dahulu menggunakan alat baris perintah EdmGen.exe atau dengan menggunakan templat Toolkit Transformasi Templat Teks (T4). Dalam tutorial ini Anda akan menggunakan templat T4.
Di folder DAL , tambahkan file menggunakan templat Templat Teks (berada di bawah simpul Umum di daftar Templat terinstal ), dan beri nama SchoolModel.Views.tt. Ganti kode yang ada dalam file dengan kode berikut:
<#
/***************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
***************************************************************************/
#>
<#
//
// TITLE: T4 template to generate views for an EDMX file in a C# project
//
// DESCRIPTION:
// This is a T4 template to generate views in C# for an EDMX file in C# projects.
// The generated views are automatically compiled into the project's output assembly.
//
// This template follows a simple file naming convention to determine the EDMX file to process:
// - It assumes that [edmx-file-name].Views.tt will process and generate views for [edmx-file-name].EDMX
// - The views are generated in the code behind file [edmx-file-name].Views.cs
//
// USAGE:
// Do the following to generate views for an EDMX file (e.g. Model1.edmx) in a C# project
// 1. In Solution Explorer, right-click the project node and choose "Add...Existing...Item" from the context menu
// 2. Browse to and choose this .tt file to include it in the project
// 3. Ensure this .tt file is in the same directory as the EDMX file to process
// 4. In Solution Explorer, rename this .tt file to the form [edmx-file-name].Views.tt (e.g. Model1.Views.tt)
// 5. In Solution Explorer, right-click Model1.Views.tt and choose "Run Custom Tool" to generate the views
// 6. The views are generated in the code behind file Model1.Views.cs
//
// TIPS:
// If you have multiple EDMX files in your project then make as many copies of this .tt file and rename appropriately
// to pair each with each EDMX file.
//
// To generate views for all EDMX files in the solution, click the "Transform All Templates" button in the Solution Explorer toolbar
// (its the rightmost button in the toolbar)
//
#>
<#
//
// T4 template code follows
//
#>
<#@ template language="C#" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#@ output extension=".cs" #>
<#
// Find EDMX file to process: Model1.Views.tt generates views for Model1.EDMX
string edmxFileName = Path.GetFileNameWithoutExtension(this.Host.TemplateFile).ToLowerInvariant().Replace(".views", "") + ".edmx";
string edmxFilePath = Path.Combine(Path.GetDirectoryName(this.Host.TemplateFile), edmxFileName);
if (File.Exists(edmxFilePath))
{
// Call helper class to generate pre-compiled views and write to output
this.WriteLine(GenerateViews(edmxFilePath));
}
else
{
this.Error(String.Format("No views were generated. Cannot find file {0}. Ensure the project has an EDMX file and the file name of the .tt file is of the form [edmx-file-name].Views.tt", edmxFilePath));
}
// All done!
#>
<#+
private String GenerateViews(string edmxFilePath)
{
MetadataLoader loader = new MetadataLoader(this);
MetadataWorkspace workspace;
if(!loader.TryLoadAllMetadata(edmxFilePath, out workspace))
{
this.Error("Error in the metadata");
return String.Empty;
}
String generatedViews = String.Empty;
try
{
using (StreamWriter writer = new StreamWriter(new MemoryStream()))
{
StorageMappingItemCollection mappingItems = (StorageMappingItemCollection)workspace.GetItemCollection(DataSpace.CSSpace);
// Initialize the view generator to generate views in C#
EntityViewGenerator viewGenerator = new EntityViewGenerator();
viewGenerator.LanguageOption = LanguageOption.GenerateCSharpCode;
IList<EdmSchemaError> errors = viewGenerator.GenerateViews(mappingItems, writer);
foreach (EdmSchemaError e in errors)
{
// log error
this.Error(e.Message);
}
MemoryStream memStream = writer.BaseStream as MemoryStream;
generatedViews = Encoding.UTF8.GetString(memStream.ToArray());
}
}
catch (Exception ex)
{
// log error
this.Error(ex.ToString());
}
return generatedViews;
}
#>
Kode ini menghasilkan tampilan untuk file .edmx yang terletak di folder yang sama dengan templat dan yang memiliki nama yang sama dengan file templat. Misalnya, jika file templat Anda diberi nama SchoolModel.Views.tt, file model data bernama SchoolModel.edmx akan mencari file model data bernama SchoolModel.edmx.
Simpan file, lalu klik kanan file di Penjelajah Solusi dan pilih Jalankan Alat Kustom.
Visual Studio menghasilkan file kode yang membuat tampilan, yang diberi nama SchoolModel.Views.cs berdasarkan templat. (Anda mungkin telah memperhatikan bahwa file kode dibuat bahkan sebelum Anda memilih Jalankan Alat Kustom, segera setelah Anda menyimpan file templat.)
Anda sekarang dapat menjalankan aplikasi dan memverifikasi bahwa aplikasi berfungsi seperti sebelumnya.
Untuk informasi selengkapnya tentang tampilan yang telah dibuat sebelumnya, lihat sumber daya berikut ini:
-
Cara: Tampilan Pra-Hasil untuk Meningkatkan Performa Kueri di situs web MSDN. Menjelaskan cara menggunakan
EdmGen.exe
alat baris perintah untuk membuat tampilan sebelumnya. - Mengisolasi Performa dengan Tampilan yang Telah Dikompresi/Telah Dibuat sebelumnya di Kerangka Kerja Entitas 4 di blog Tim Penasihat Pelanggan Windows Server AppFabric.
Ini menyelesaikan pengantar untuk meningkatkan performa dalam aplikasi web ASP.NET yang menggunakan Kerangka Kerja Entitas. Untuk informasi selengkapnya, lihat sumber berikut ini:
- Pertimbangan Performa (Kerangka Kerja Entitas) di situs web MSDN.
- Posting terkait performa di blog Tim Kerangka Kerja Entitas.
-
Opsi Penggabungan EF dan Kueri yang Dikompilasi. Posting blog yang menjelaskan perilaku tak terduga dari kueri yang dikompilasi dan opsi penggabungan seperti
NoTracking
. Jika Anda berencana menggunakan kueri yang dikompilasi atau memanipulasi pengaturan opsi penggabungan di aplikasi Anda, baca ini terlebih dahulu. - Postingan terkait Kerangka Kerja Entitas di blog Tim Penasihat Pelanggan Data dan Pemodelan. Menyertakan postingan tentang kueri yang dikompilasi dan menggunakan Visual Studio 2010 Profiler untuk menemukan masalah performa.
- ASP.NET Rekomendasi Manajemen Status.
- Menggunakan Kerangka Kerja Entitas dan ObjectDataSource: Halaman Kustom. Posting blog yang dibangun pada aplikasi ContosoUniversity yang dibuat dalam tutorial ini untuk menjelaskan cara menerapkan penomoran halaman di halaman Departments.aspx .
Tutorial berikutnya meninjau beberapa penyempurnaan penting untuk Kerangka Kerja Entitas yang baru di versi 4.