標籤:
轉自:http://www.cnblogs.com/huangcong/archive/2011/07/20/1931107.html在之前的文本模板(T4)初體驗中我們已經知道了T4的用處,下面就看看如何用它來實現批量修改Entity Framework(Entity Framework)中的類名.我們都知道ADO.NET 實體資料模型中有一種方式是以資料庫模型來產生資料模型的,這是個很簡便的實體資料模型產生的方式,但是因為微軟提供的自訂介面不足,我們無法實現對產生的資料模型實體類批量進行修改(至少我上網找了很久沒找到方法,哪位大俠知道的請賜教,這困擾我很久了,或者哪個好人做有批量修改軟體的,麻煩共用一下哈),當然你可以在edmx檔案的視圖環境下對錶進行一個個的修改,但是這個步驟不僅繁瑣,而且當你修改資料庫結構描述,重建實體資料架構的時候,之前的手工修改將全部被覆蓋,因此一旦有資料庫的修改,就是噩夢的開始了.因此,必須找到一個靈活的方法來解決這個辦法,而我想到的是用基於T4的ADO.NET 自我追蹤實體產生器來解決問題.下面就來看如何?吧.需求分析:
最近的一個系統中資料庫結構描述的表結構比較複雜,有幾十個表,而一些基礎資料表的名字是以 Base_XXX(XXX為表名) 來命名的,這導致我在用實體資料模型中不得不以如下的方式進行資料操作:
UserCenterEntities dataBase = new UserCenterEntities();
//擷取所有使用者
dataBase.Base_User.Select(u => u).ToList();
從上面可以看出,資料庫中的Base_User表映射的是Base_User類. 但是我希望Base_User表映射的類名為UserEntity.即代碼風格希望如下所示:
UserCenterEntities dataBase = new UserCenterEntities();
//擷取所有使用者
dataBase.UserEntity.Select(u => u).ToList();
當然,大家要說了,這有什麼難,最簡單的方法就是直接在實體資料模型視圖編輯器中修改表映射名稱就可以啦:
這個方法固然可行,但是如果要我這樣修改幾十個表,並且一旦資料庫有所修改又得重新全部命名一次,我想我會崩潰的,因此,必須尋求一個合適的方法,那就是使用基於T4的ADO.NET自我追蹤實體產生器.下面就看看如何?的吧.
1) 資料庫準備為了簡單示範,我就只建立一個2個表的示範資料庫吧,大家請用自己的資料庫運行一下SQL語句,產生一個新的資料庫.代碼2) 建立資料Entity Framework開啟VS2010,建立一個新的控制台工程,在工程上右鍵--建立項--ADO.NET 實體資料模型:
選擇"從資料庫產生"--下一步--建立串連--添加我們剛才建立好的TestDB資料庫--下一步:
選擇所有的資料庫物件--完成,這樣我們就得到最初的實體資料模型了:
開啟Model1.Designer.cs,可以看到2個實體類名都不是我想要的.
好了,下面就看看怎麼批量修改實體類名吧,ADO.NET自我追蹤實體產生器終於可以粉墨登場啦~3) 建立ADO.NET自我追蹤實體產生器.在實體資料模型試圖編輯器中右鍵--添加代碼產生器--選擇ADO.NET 自我追蹤實體產生器.
添加之後,我們可以在工程中發現多了2個模板以及同步產生的類檔案:
4) 修改Model1.tt模板開啟Model1.tt檔案,並且在檔案的最後添加如下代碼:代碼
接著找到下面這段代碼:
// 發出實體類型
foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
{
fileManager.StartNewFile(entity.Name + ".cs");
BeginNamespace(namespaceName, code);
WriteEntityTypeSerializationInfo(entity, ItemCollection, code, ef);
#>
<#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class <#=code.Escape(entity)#><#=code.StringBefore(" : ", code.Escape(entity.BaseType))#><#=entity.BaseType == null ? ": " : ","#>IObjectWithChangeTracker, INotifyPropertyChanged
{
<#
更換為如下代碼,並且儲存:
// 發出實體類型
foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
{
fileManager.StartNewFile(GetClassName(entity.Name,"Entity") + ".cs");
BeginNamespace(namespaceName, code);
WriteEntityTypeSerializationInfo(entity, ItemCollection, code, ef);
#>
<#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class <#=GetClassName(code.Escape(entity),"Entity")#><#=code.StringBefore(" : ", code.Escape(entity.BaseType))#><#=entity.BaseType == null ?": " : ", "#>IObjectWithChangeTracker, INotifyPropertyChanged
{
<#之後我們可以看到工程檔案的檔案名稱和類名都批量修改為我們想要的名稱了:
5) 修改Model1.Context.tt模板開啟Model1.Context.tt檔案,並且在檔案的最後添加如下代碼:代碼
接著找到如下代碼:
<#
region.Begin("ObjectSet 屬性", 2);
foreach (EntitySet entitySet in container.BaseEntitySets.OfType<EntitySet>())
{
#>
<#=Accessibility.ForReadOnlyProperty(entitySet)#> ObjectSet<<#=code.Escape(entitySet.ElementType)#>> <#=code.Escape(entitySet)#>
{
get { return <#=code.FieldName(entitySet) #> ?? (<#=code.FieldName(entitySet)#> = CreateObjectSet<<#=code.Escape(entitySet.ElementType)#>>("<#=entitySet.Name#>")); }
}
private ObjectSet<<#=code.Escape(entitySet.ElementType)#>> <#=code.FieldName(entitySet)#>;
<#
改為如下代碼,並且儲存:
<#
region.Begin("ObjectSet 屬性", 2);
foreach (EntitySet entitySet in container.BaseEntitySets.OfType<EntitySet>())
{
string className = GetClassName(code.Escape(entitySet.ElementType),"Entity");
string entitySetElementType = GetClassName(code.Escape(entitySet.ElementType),"Entity");
#>
<#=Accessibility.ForReadOnlyProperty(entitySet)#> ObjectSet<<#=className#>> <#=GetClassName(code.Escape(entitySet),"Entity")#>
{
get { return <#=code.FieldName(entitySet) #> ?? (<#=code.FieldName(entitySet)#> = CreateObjectSet<<#=className#>>("<#=entitySet.Name#>")); }
}
private ObjectSet<<#=entitySetElementType#>> <#=code.FieldName(entitySet)#>;
<#開啟Model1.Context.cs檔案,可以看到裡面的類名也批量修改為我們想要的了:
6) 測試
C#代碼產生工具:文本模板初體驗 使用T4批量修改Entity Framework(Entity Framework)的類名