2014年4月4日 星期五

ASP.NET MVC 4 Model 中 Virtual 的作用

在 View 端專寫時,顯示某一張表的資料,若未使用到相對應的關聯表,則不載入此表資料;若使用,則載入。這個作用就是延遲載入 ( Lazy Load ),使用再載入,很類似非同步的概念,而在 Model 關聯成員加上 Virtual 關鍵字,就可以做到延遲載入的作用。

寫個例子來表示一下差別,資料庫使用北風資料庫利用 Database first 建置,可以參考 Visual Studio 2012 安裝 Northwind 資料庫並建立 Entity Framework Database First ( .edmx )

接著建置 CRUD 的介面,我是使用 Products 這張資料表建置,可以參考:

建置完成後,顯示頁面如下:

Products Model 內容如下,建置出來就已經有 virtual :
public partial class Products
{

    public Products()
    {
        this.Order_Details = new HashSet<Order_Details>();

    }

    public int ProductID { get; set; }
    public string ProductName { get; set; }
    public Nullable<int> SupplierID { get; set; }
    public Nullable<int> CategoryID { get; set; }
    public string QuantityPerUnit { get; set; }
    public Nullable<decimal> UnitPrice { get; set; }
    public Nullable<short> UnitsInStock { get; set; }
    public Nullable<short> UnitsOnOrder { get; set; }
    public Nullable<short> ReorderLevel { get; set; }
    public bool Discontinued { get; set; }

    public virtual Categories Categories { get; set; }
    public virtual ICollection<Order_Details> Order_Details { get; set; }
    public virtual Suppliers Suppliers { get; set; }

}

在 ProductsController 內 Get 程式碼如下:
public ActionResult Index()
{
    var products = db.Products;
    return View(products.ToList());
}

接著將 Products Model 內的關聯成員的 virtual 關鍵字拿掉後執行畫面如下:

看出差別了嗎? CategoryName 不會顯示出來,我們回到 View 端看一下它的程式碼:
@Html.DisplayNameFor(model => model.Categories.CategoryName)

這就是所謂的延遲載入的差異,如果將 virtual 關鍵字拿掉,就使用到此關聯成員時,就不會載入;而若有 virtual 關鍵字,則會載入。在 Controller 端其實都沒有變,而是 virtual 使它變得更靈活。

如果真的不加也有另外的做法,就是在資料讀取時,就關聯表的資料 Include 進來:
public ActionResult Index()
{
    var products = db.Products.Include(x => x.Categories);
    return View(products.ToList());
}


沒有留言 :

張貼留言

Related Posts Plugin for WordPress, Blogger...