博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
黄聪:C#代码生成工具:文本模板初体验 使用T4批量修改实体框架(Entity Framework)的类名...
阅读量:6226 次
发布时间:2019-06-21

本文共 5009 字,大约阅读时间需要 16 分钟。

C#代码生成工具:文本模板初体验 使用T4批量修改实体框架(Entity Framework)的类名

在之前的中我们已经知道了T4的用处,下面就看看如何用它来实现批量修改实体框架(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语句,生成一个新的数据库.

代码
Create
DataBase
TestDB
GO
Use
TestDB
GO
Create
Table
Base_User
(
Id
int
not
null
PRIMARY
KEY
,
RoleId
int
null
,
Name
varchar
(
50
)
not
null
)
GO
Create
Table
Base_Role
(
Id
int
not
null
PRIMARY
KEY
,
Name
varchar
(
50
)
not
null
)
GO

2) 创建数据实体框架

打开VS2010,创建一个新的控制台工程,在工程上右键--新建项--ADO.NET 实体数据模型:

选择"从数据库生成"--下一步--新建连接--添加我们刚才创建好的TestDB数据库--下一步:

选择所有的数据库对象--完成,这样我们就得到最初的实体数据模型了:

打开Model1.Designer.cs,可以看到2个实体类名都不是我想要的.

好了,下面就看看怎么批量修改实体类名吧,ADO.NET自跟踪实体生成器终于可以粉墨登场啦~

3) 创建ADO.NET自跟踪实体生成器.

在实体数据模型试图编辑器中右键--添加代码生成器--选择ADO.NET 自跟踪实体生成器.

添加之后,我们可以在工程中发现多了2个模板以及同步生成的类文件:

4) 修改Model1.tt模板

打开Model1.tt文件,并且在文件的最后添加如下代码:

代码
<
#
+
//
获取类名
string
GetClassName(
string
tableName)
{
return
GetClassName(tableName,
""
);
}
//
获取类名
string
GetClassName(
string
tableName,
string
lastStr)
{
string
[] name
=
tableName.Split(
'
_
'
);
string
className
=
tableName;
if
(name.Length
>
0
)
{
className
=
name[name.Length
-
1
];
}
return
className
+
lastStr;
}
#
>

接着找到下面这段代码:

//
发出实体类型
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文件,并且在文件的最后添加如下代码:

代码
<
#
+
//
获取类名
string
GetClassName(
string
tableName)
{
return
GetClassName(tableName,
""
);
}
//
获取类名
string
GetClassName(
string
tableName,
string
lastStr)
{
string
[] name
=
tableName.Split(
'
_
'
);
string
className
=
tableName;
if
(name.Length
>
0
)
{
className
=
name[name.Length
-
1
];
}
return
className
+
lastStr;
}
#
>

接着找到如下代码:

<
#
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) 测试

转载地址:http://ktuna.baihongyu.com/

你可能感兴趣的文章
移植Qt4.8.4项目到QT5.2上时遇到的一些问题
查看>>
Dot Graphviz Manual
查看>>
$.Ajax发送请求的注意事项
查看>>
Redis学习笔记7--Redis管道(pipeline)
查看>>
eclipse下jetty启动后不能编辑css的问题
查看>>
mysql中sql语句使日期增加一年
查看>>
视频分享网站首页:最热视频特效
查看>>
EditPlus行首行尾批量添加字符
查看>>
StuQ技能图谱
查看>>
惊艳!9个不可思议的 HTML5 Canvas 应用试验
查看>>
Java 8 停止维护,Java 9 难产,IDEA 2018 发布,还有……
查看>>
[leetcode] Search in Rotated Sorted Array
查看>>
Deprecated: mysql_connect(): The mysql extension i
查看>>
AndroidStudio3.0a 中 Kotlin 直接使用控件。
查看>>
java 复习-字符型变量
查看>>
mysql事务、表锁、行锁
查看>>
Cortex-M0详解(1) -- 工作状态及模式
查看>>
在gexmul上移植u-boot
查看>>
Win7发布热点
查看>>
python pip install 出现 OSError: [Errno 1] Operation not permitted
查看>>