2013年12月23日 星期一

修改 ASP.NET Identity 預設的 Table Name

測試環境: VS2013、MV5、Windows7



之前的幾篇有關 ASP.NET Identity 貼文中已經很清楚的了解如何新加入額外的欄位在Users Table 中,今天要來測試的是有沒有辦法由我們自行決定那些 ASP.NET Identity 架構所產生的Tables 的 Table Name呢?也許在您的應用程式中有某些特別的原因必須自行控制資料庫中Table 的名稱,包含由 ASP.NET Identity 所自動產生的系統 Tables,本文就來看看要如何達到這要的需求!



貼文內容:
  • 建立MVC5新專案並執行
  • 修改Tables Name
  • 啟動 Migration 功能
  • 更新資料庫
  • 執行結果




建立MVC5新專案

一樣透過VS2013 範本建立新專案, "檔案"=>"新增"=>”專案",選擇 Web 範本中的 “ASP.NET Web應用程式,按確定鍵後,於”新增ASP.NET專案”
視窗中點選"MVP”範本,並確定驗證方式是"個別使用者帳號"。完成專案建立後當您啟動系統,第一次登入時會自動ASP.NET Identity 所使用的那五個Tables(如下圖)





(請特別注意 ASPNetUsers中的第一個欄位名稱為Id)




修改Table Name

在AspNet.Identity抽象架構中二個主要的觀念就是 users 和 stores。 users 指的是系統中使用者的相關資訊,而stores 則是將使用者帳戶資訊儲存至資料來源(data source)中及由資料來源(data source)讀取出來。在ASP.NET Identity架構下最主要的二個組件(Assembly)是 Microsoft.AspNet.Identity.Core 及 Microsoft.AspNet.Identity.EntityFramework,這二個組件的主要功能正好就是對映到前述的二個觀念中。

在Identity.Core中有二個主要的 class : UserManager 及 RoleManager,其中UserManager可以說是最重要的,它是被使用來建立、搜尋/取得、移除:
  • Users
  • Passwords
  • Claims
  • Link to roles
  • Link to logins



而在 Microsoft.AspNet.Identity.EntityFramework的UserStore則負責將由UserManager所產生的使用者帳戶物件寫入至資料來源/由資料來源讀取出來。

由前述的說明中可以知道要想要達成的"資料表(table name )更名"需求可以從Microsoft.AspNet.Identity.EntityFramework中IdentityDbContext的 OnModelCreating() 來動手腳。



首先用 Dot Net Reflector 打開Microsoft.AspNet.Identity.EntityFramework,找到 IdentityDbContext class,檢視一下 OnModelCreating() 就會發現由系統自動產生的的預設Table Name就在這段程式中,同時注意到它是可覆寫的。



接下來要開始改寫的工作,先找到 “Models”目錄下的”IdentityModels.cs” 中的 ApplicationDbContext class (如下圖)



在這個class 中去覆寫 OnModelCreating() method



完整程式如下:
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq.Expressions;

namespace ToDoProject.Models
{
   // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
   public class ApplicationUser : IdentityUser
   {
       [Display(Name="所在城市")]
       public string HomeTown { get; set; }
       public DateTime? BirthDate { get; set; }
       public virtual ICollection<ToDo> ToDoes { get; set; }
   }

   public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
   {
       public ApplicationDbContext()
           : base("DefaultConnection")
       {
       }

       public DbSet<ToDo> ToDoes { get; set; }

       protected override void OnModelCreating(DbModelBuilder modelBuilder)
       {
           modelBuilder.Entity<IdentityUser>().ToTable("MyUsers").Property(p => p.Id).HasColumnName("UserId");
           modelBuilder.Entity<ApplicationUser>().ToTable("MyUsers").Property((Expression<Func<ApplicationUser, string>>)(u => u.UserName)).IsRequired();
           modelBuilder.Entity<ApplicationUser>().HasMany<IdentityUserRole>(u => u.Roles);
           modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { UserId = r.UserId, RoleId = r.RoleId }).ToTable("MyUserRoles");
           modelBuilder.Entity<IdentityUserLogin>().HasKey(l => new { UserId = l.UserId, LoginProvider = l.LoginProvider, ProviderKey = l.ProviderKey }).ToTable("MyUserLogins").HasRequired<IdentityUser>(u => u.User);
           modelBuilder.Entity<IdentityUserClaim>().ToTable("MyUserClaims").HasRequired<IdentityUser>(u => u.User);
           modelBuilder.Entity<IdentityRole>().ToTable("MyRoles").Property((Expression<Func<IdentityRole, string>>)(r => r.Name)).IsRequired();
       }
   }
}




啟動 Migration功能



更新資料庫






更新資料庫成功後,透過伺服器總管,可以看到系統所產生的Table Name 已經都變成我們自行定義的名稱了,甚至連 Users Table 中的 Primary Key都由預設的ID改變成 UserId了。




參考文章:


沒有留言:

張貼留言