⑴ 创建代码生成器可以很简单:如何通过T4模板生成代码[下篇]
在《上篇》中我们通过T4模板为我们指定的数据表成功生成了我们需要的用于添加、修改和删除操作的存储过程。但是这是一种基于单个文件的解决方案,即我们必须为每一个生成的存储过程建立一个模板。如果我们提供一种基于多文件的代码生成方式,将会为编程人员带来极大的便利。借助于T4 ToolBox这个开源工具箱,多文件的SQL Generator的实现变得异常简单。[文中的例子可以从这里下载]目录
二、创建自定义的Generator
三、ProcereGenerator如何被使用?一、多文件代码生成器会带来多大的便利?我们先来直观的感受一下较之《上篇》提供的单一文件的代码生成器,基于多文件的代码生成解决方案会为开发人员带来多大的便利。 同样对于《上篇》创建的数据表T_PRODUCT,之前我们为了生成三个不同的存储过程,我们不得已需要创建3个不同的T4模板文件。实际上我们更需要的方式只需要创建一个T4模板,让我们的SQL Generator自动为我们生成3个包含相应存储过程的.sql附属文件,如左图所示(点击看大图)。有的时候,基于单个数据表的存储过程生成方式我们依然觉得不方便。如果我们能够在T4模板文件中指定的数据表的列表,让我们的SQL Generator为列表的每一个数据表都生成CUD三个存储过程,这样的方式更加具有吸引力。如右图所示(点击看大图),一个订单模块包含两个具有主子关系的两张表(T_ORDER和T_ORDER_DETAIL),现在我们在一个T4模板中指定这两个表明,通过SQL Generator可以帮助我们生成6个包含存储过程的.sql附属文件。甚至有的时候我们连数据表列表都无需指定,让SQL Generator为所有的表都生成相应的存储过程。我的例子中没有提供这样的功能,但是实现自来不会存在任何问题。二、创建自定义的Generator在《上篇》中我创建了一个抽象的ProcereTemplate类,以及三个基于生成CUD存储过程的具体ProcereTemplate:InsertProcereTemplate、UpdateProcereTemplate和DeleteProcereTemplate。它们都将直接服务于我们今天将要提供的基于多文件的SQL Generator。在《上篇》中,这四个Template分别定义在4个不同的TT文件中,3个具体的ProcereTemplate通过<#@include>指令将抽象ProcereTemplate模板文件包含过来。由于我们将要创建的T4模板将会使用到这四个类,如果我们用四个<#@include>指令将四个TT文件包含过来,由于T4引擎将会导致对ProcereTemplate的4次包含,最好将会导致变异问题。个人觉得这应该算是T4引擎解析包含关系的一个局限性,为了解决这个问题我们不得不抽象的ProcereTemplate和三个具体的ProcereTemplate都合并成一个TT文件。T4 ToolBox为类库中为了提供了一个抽象的T4Toolbox.Generator类用于实现多文件的代码生成。为此我们创建一个TT模板文件,定义了如下一个继承自该类的ProcereGenerator。ProcereGenerator的核心是通过属性Templates定义的类型为IEnumerable<ProcereTemplate>的ProcereTemplate列表,这个列表在存储过程中进行初始化。而对于ProcereGenerator的构造函数,处理定义了一个表示数据库连接字符串的databaseName的参数外,并以数组参数的形式指定了生成的存储过程基于的数据表名的列表。<#@ import namespace="System.Collections.Generic" #><#@ include file="ProcereTemplate.tt" #><#@ include file="T4Toolbox.tt" #><#+publicclass ProcereGenerator : Generator{public IEnumerable<ProcereTemplate> Templates{get; private set;}public ProcereGenerator(string databaseName, paramsstring[] tableNames) {if(null == tableNames || tableNames.Length == 0) {thrownew ArgumentNullException("tableNames"); } this.Templates = InitlizeTemplates(databaseName,tableNames); }private IEnumerable<ProcereTemplate> InitlizeTemplates(string databaseName, string[] tableNames) { foreach(string tableName in tableNames) {yieldreturnnew InsertProcereTemplate(databaseName, tableName);yieldreturnnew UpdateProcereTemplate(databaseName, tableName);yieldreturnnew DeleteProcereTemplate(databaseName, tableName); } }protectedoverridevoid RunCore() {foreach(ProcereTemplate tempalte inthis.Templates) { tempalte.RenderToFile(tempalte.GetProcereName() + ".sql"); } }}#>真正的存储过程的T-SQL脚本实现在重写的RunCore中。由于具体的文本转化逻辑都定义在了ProcereTemplate中了,所以在这里我们需要遍历的ProcereTemplate集合中每一个Template对象,调用RenderToFile方法将相应的存储过程的脚本写入以存储过程命名同名的.sql文件中。三、ProcereGenerator如何被使用?我们最后来看看我们创建的ProcereGenerator最终如何被应用于具体的代码生成。其实很简单,我们只需要创建相应的模板文件,通过<#@include>将定义ProcereGenerator类的TT文件包含近来,最后以代码语句调用块(<#StatementCode#>)的形式实力化该对象,并调用Run方法即可。在构造函数中指定数据库连接字符串的名称和数据表名的列表。下面是基于但表的T4模板。<#@ template language="C#" hostSpecific="true" debug="true" #><#@ include file="Templates\ProcereGenerator.tt" #><#new ProcereGenerator("TestDb","T_PRODUCT").Run();#>下面是基于多表的T4模板:<#@ template language="C#" hostSpecific="true" debug="true" #><#@ include file="Templates\ProcereGenerator.tt" #><#new ProcereGenerator("TestDb","T_ORDER","T_ORDER_DETAIL").Run();#>当你代码生成工作执行之后,会多出一个与TT文件同名的附属文件,你需要手工删除掉它。从数据到代码——通过代码生成机制实现强类型编程[上篇]从数据到代码——通过代码生成机制实现强类型编程[下篇]从数据到代码——基于T4的代码生成方式创建代码生成器可以很简单:如何通过T4模板生成代码?[上篇]
⑵ 如何提取PPT模版,并应用于另一个PPT中
1、首先将需要添加到另一个PPT中作为模板的PPT文件点击保存。
⑶ 下载的ppt模板怎么用
先打开自己希望更改模板的演示文稿,然后选择“设计”→“主题”,点击下拉箭头,单击“浏览主题”。然后就可以在弹出的“选择主题或主题文档”对话框中选择想要借用的模板文件potx或者是pptx、pPS文件,甚至可以选择一个Web页文件来作为模板。
单击板块上的模板类型链接(如“幻灯片背景”→“美食”),就可以在右侧板块看到该类模板的名称和提供商等内容。点击“下载”按钮即可将模板下载到你的硬盘中,并会自动用PowerPoint打开该模板。如果你对模板的效果满意,可以用“另存为”将它保存为模板,以后就可以像普通模板那样方便调用了。
⑷ 包含类功能的模板必须以类功能结尾
估计你是用错括号了 , , , 代码块是用<# #> , 表达式块是<#= #> 写一个类的话使用 <#+ #>
⑸ 如何看到 ef emdx.xml
一、使用存储过程的必要性我们知道EF通过元数据,即概念模型(ConceptModel)、存储模型(StorageModel)和概念/存储映射(C/SMapping),和状态追踪(StateTracking)机制可以为基于模型的操作自动生成SQL。对于一些简单的项目开发,这是非常理想的,因为他们完全可以不用关注数据存储层面的东西,你可以采用一些完全不具有数据库知识的开发者。但是理想总归是理想,对于企业级开发来说,我们需要的是对数据库层面数据的操作有自己的控制。在这方面,我们可以随便举两个典型的场景:逻辑删除:对于一些重要的数据,我们可能需要让它们永久保存。当我们试图“删除”这些数据的时候,我们并不是将它们从数据表中移除(物理删除),而是为这条记录作一个已经被删除的标记;并发处理:为了解决相同的数据在获取和提交这段时间内被另一个用户修改或者删除,我们往往SQL层面增加并发控制的逻辑。比较典型的做法是在每一个表中添加一个VersionNo这样的字段,你可以采用TimeStamp,也可以直接采用INT或者GUID。在执行Update或者Delete的SQL中判断之前获取的VersionNo是否和当前的一致。让解决这些问题,就不能使用EF为我们自动生成的SQL,只有通过使用我们自定义的存储过程。二、实现存储过程自动匹配的必要条件本篇文章提供的存储过程自动映射机制是通过代码生成的方式完成的。说白了,就是读取原来的.edmx模型文件,通过分析在存储模型中使用的数据表,导入基于该表的CUD存储过程;然后再概念/存储映射节点中添加实体和这些存储过程的映射关系。那实现这样的代码生成,需要具有如下三个固定的映射规则。数据表名-存储过程名:这个映射关系帮助我们通过存储模型中的实体名找到对应CUD三个存储过程(如果实体是数据表);数据表列名-存储过程参数名:当存储过程被执行的时候,通过这个映射让概念模型实体某个属性值作为对应的参数;存储过程参数名-版本:当进行参数赋值的时候,通过这个映射决定是使用Original或者Current版本。在实际的开发过程中,这样的标准存储过程一般都是通过代码生成器生成的(在我的文章《创建代码生成器可以很简单:如何通过T4模板生成代码?[下篇]》中有过相应的实现),它们具有这样的映射关系。基于这三种映射关系,我定义了如下一个名为IProcereNameConverter的接口。其中OperationKind是我自定义的一个表示CUD操作类型的枚举。1::{3:stringGetProcereName(stringtableName,OperationKindoperationKind);4:stringGetColumnName(stringparameterName);5:DataRowVersionGetVersion(stringparameterName);6:}7:8:publicenumOperationKind9:{10:Insert,11:Update,12:Delete13:}按照我们当前项目采用的命名规范,我定义了如下一个默认的DefaultNameConverter。它体现的是这样的映射关系,比如有个数据表明为T_USER(大写,单词之间用“_”隔开,并以T_为前缀),它对应的CUD存储过程名分别为:P_USER_I、P_USER_U和P_USER_D(大写,以代表存储过程的P_为前缀,后缀_I/U/D表示CUD操作类型,中间为去除前缀的表名)。如果列名为USER_ID,参数名为p_user_id(小写,加p_前缀)。如果需要用Original值为参数赋值,需要将p_前缀改成o_前缀(o_user_id)。1::IProcereNameConverter2:{3:publicstringGetProcereName(stringtableName,OperationKindoperationKind)4:{5:switch(operationKind)6:{7:caseOperationKind.Insert:8:returnstring.Format("P_{0}_I",tableName.Substring(2));9:caseOperationKind.Update:10:returnstring.Format("P_{0}_U",tableName.Substring(2));11:default:12:returnstring.Format("P_{0}_D",tableName.Substring(2));13:}14:}15:16:publicstringGetColumnName(stringparameterName)17:{18:returnparameterName.Substring(2).ToUpper();19:}20:21:(stringparameterName)22:{23:if(parameterName.StartsWith("o"))24:{25:returnDataRowVersion.Original;26:}27:else28:{29:returnDataRowVersion.Current;30:}31:}32:}三、通过T4生成新的.edmx模型我们采用的基于T4的代码生成,了解EF的应该对T4不会感到陌生了。如果对代码生成感兴趣的话,可以看看我的文章《与VS集成的若干种代码生成解决方案[博文汇总(共8篇)]》。这里利用借助于T4ToolBox这个开源工具箱,并采用SQLServerSMO获取存储过程信息。所有涉及到的文本转化都实现在如下一个ProcereMappingTemplate类型中,由于内容较多,具体实现就忽略了,有兴趣的朋友可能下载源代码。ProcereMappingTemplate具有两个构造函数的参数分别表示:源.edmx文件,服务器和数据库名,存储过程的Schema(默认为dbo)和具体的ProcereNameConverter(默认为DefaultNameConverter)。1::Template2:{3:publicXmlDocumentSourceModel{get;privateset;}4:{get;privateset;}5:publicDatabaseDatabase{get;privateset;}6:publicstringSchema{get;privateset;}7:8:publicProcereMappingTemplate(stringsourceModelFile,stringserverName,stringdatabaseName);9:publicProcereMappingTemplate(stringsourceModelFile,stringserverName,stringdatabaseName,10:,stringschema);11:12:();13:();14:()15:{16:XElementnewStorageModelNode=this.GenerateStorageModelNode();17:XElementnewMappingNode=this.GenerateMappingNode();18:19:XmlNodestorageModelNode=this.SourceModel.GetElementsByTagName("edmx:StorageModels")[0];20:storageModelNode.InnerXml=newStorageModelNode.Elements().ToArray()[0].ToString();21:22:XmlNodemappingNode=this.SourceModel.GetElementsByTagName("edmx:Mappings")[0];23:mappingNode.InnerXml=newMappingNode.Elements().ToArray()[0].ToString();24:25:this.WriteLine("");26:this.Write(this.SourceModel.DocumentElement.OuterXml.Replace("xmlns=\"\"",""));27:returnGenerationEnvironment.ToString();28:}29:}在使用过程中,你只需要在tt模板中创建这个ProcereMappingTemplate对象,调用Render方法即可。1:2:3:4:5:6:7:8:9:四、看看生成出来的.emdx通过上面创建的TT模板(你指定的数据库中一定要存在具有相应映射关系的存储过程),新的.edmx模型文件会作为该tt文件的依赖文件被生成出来。而这个新生成的.edmx具有存储过程映射信息。具体来说,下面是原始的.edmx文件(只保留元数据节点)。1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20:21:22:23:24:25:26:27:28:29:30:31:32:33:34:35:36:37:38:39:40:41:42:43:44:45:46:47:48:49:50:51:
⑹ C#如何手动设置AssemblyVersion("1.0.*")的生成规则
默认用时间可能有它自己的原因,包括防止版本号重复、易于生成等。
如果像你说的用编译内次数,那么至少还容得有个文件存储相应的次数吧?
查了下,有t4模板的(不知道你上面说的是不是这个),也有现成的github开源插件的,也有自定义build task的,你自己看看
stackoverflow.com/questions/43019832/auto-versioning-in-visual-studio-2017-net-core
网页链接
⑺ 如何手工将Entity Framework 4.0升级到5.0
第一步:从NuGet安装Entity Framework 5.0
首先,对现有的EF4.0项目,什么都不要改,也不要删。直接从NuGet安装EF5。如果你是.NET4的项目,那实际上安装的是4.4版的DLL,所以EF5的枚举类型是不可以用的。如果你已经升级了.NET4.5,那就是完完全全的EF5。
NuGet会自动给你添加引用以及配置相关的config文件。
第二步:更新EDMX
打开现有的EDMX文件,在空白处点击右键,选择“Add Code Generation Item”
新版EF是用T4模板来生成一个个实体类的,而4.0中是撸在一个edmx里的,所以我们要选择一种模板,这里明显只有一种可选:
EF 5.x DbContext Generator
然后,VS会弹好几个对话框,问你敢不敢运行生成脚本。显然我们要确认运行。VS一顿小撸之后,你的新版EF实体类就生成好了:
第三步:更新CUD方法
现在,你的程序肯定编译不过。因为EF4.0以后,增、删、改的API变了。所以我们要对旧代码做一些改动。
1. 插入操作:现在使用 context.类型.Add(具体对象) 来完成
2. 删除操作:现在使用 context.类型.Remove(具体对象) 来完成
3. 更新操作:现在不需要Attach了,使用 context.Entry(具体对象).State = System.Data.EntityState.Modified 来完成
4. 如果你还需要ObjectSet<T>类型,必须通过一个适配器来强撸:
(context as IObjectContextAdapter).ObjectContext.CreateObjectSet<类型>();
再次编译程序,应该就可以用了~
⑻ E人E本T4可以使用哪些日常的下载软件啊另外下文件存放在什么地方啊
呵呵,T4采用的是笔式交互操作系统,可运行兼容此系统的apk格式文件,你可以通过应用商城下载相关应用进行安装使用。
如果下载网页的图片及其他文件,可以到T4存储器--download文件夹下进行查看。
如果已经成功绑定手写邮件,那么通过邮件下载的文件会保存在T4存储器--attachments文件夹下。
⑼ 微软EF框架存储过程问题,VS2012+.NET4.5+EF6.1.1
我用的是5.0没这个问题,不过如果你理解T4模板的话这个问题很好解决。
这个应该是6.0重构了一些命名空间后,和VS原有的实体数据模型模板不一致了。
解决办法如下:修改你的 xx.Context.tt 文件:
if(container.FunctionImports.Any())
{
#>
usingSystem.Data.Objects;//改成usingSystem.Data.Entity.Core.Objects;
usingSystem.Data.Objects.DataClasses;
usingSystem.Linq;
<#
}
⑽ T4记事本里的文件存储有多页保存吗最近写东西多,每次一页一页的存好麻烦。
可以啊,你先点编辑,然后选查看所有页,然后再在多选项里勾选所有你要保存的记事本页,然后分享成word或者图片格式,就可以一次性存很多张了。