EF学习笔记——生成自定义实体类
使用EF,采用DataBase 模式,实体类都是按照数据库的定义自动生成,我们似乎无法干预。如果要生成自定义的实体类,该怎么做呢?
思路是这样的:
1、我们要自定义生成的实体类,都是分部类(partial),目的是对EF生成的实体类进行扩充;
2、扩充部分,预先写好在模板里,自动生成
3、每个实体类,都进行扩充
实施方法:
1、给VS2012安装两个插件:
- Devart T4 Editor:为VS提供智能提示功能。
- T4 Toolbox:在生成多文件时很有用。
2、新建文件夹T4,存放模板文件
1)创建T4 Toolbox模板文件EntityTemplate.tt,作用是生成多个实体类文件
代码如下:
<#+
// <copyright file="Entity.tt" company="cqxm">
// Copyright © . All Rights Reserved.
// </copyright> public class Entity : CSharpTemplate
{
private string _className; public Entity(string className)
{
_className = className;
} public override string TransformText()
{
base.TransformText();
#>
namespace testEF
{
public partial class <#= _className #> : IEntity
{
public string _ID
{
get
{
return Id.ToString();
}
}
}
}
<#+
return this.GenerationEnvironment.ToString();
}
}
#>
2)创建T4模板文件EntityOutput.tt,调用前面写的EntityTemplate.tt,真正生成各种实体类文件
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#@ include file="T4Toolbox.tt" #>
<#@ include file="EntityTemplate.tt" #>
<#
string curPath = Path.GetDirectoryName(Host.TemplateFile);
string destPath = Path.Combine(curPath, @"..\Partial");//将各个扩充实体类文件生成到文件夹Partial下
if(!Directory.Exists(destPath))
{
Directory.CreateDirectory(destPath);
}
const string inputFile = @"..\ShowMe.edmx";
var textTransform = DynamicTextTransformation.Create(this);
var itemCollection = new EdmMetadataLoader(textTransform.Host, textTransform.Errors).CreateEdmItemCollection(inputFile);
foreach (var entity in GetItemsToGenerate<EntityType>(itemCollection))
{//每个实体类都要自动生成扩充文件,是自动哦,参考文章里介绍的是手动输入实体类名称
Entity template = new Entity(entity.Name);
string fileName = string.Format(@"{0}\{1}.cs", destPath, entity.Name);
template.Output.Encoding = Encoding.UTF8;
if(File.Exists(fileName))
{
File.Delete(fileName);
}
template.RenderToFile(fileName);
}
#> <#+
/*以下代码都是为了获得EF自动生成的所有实体类名单,抄自 *.edmx\*.Context.tt。
没办法,谁叫俺看不懂哪些代码呢
*/
public class EdmMetadataLoader
{
private readonly IDynamicHost _host;
private readonly System.Collections.IList _errors; public EdmMetadataLoader(IDynamicHost host, System.Collections.IList errors)
{
ArgumentNotNull(host, "host");
ArgumentNotNull(errors, "errors"); _host = host;
_errors = errors;
} public IEnumerable<GlobalItem> CreateEdmItemCollection(string sourcePath)
{
ArgumentNotNull(sourcePath, "sourcePath"); if (!ValidateInputPath(sourcePath))
{
return new EdmItemCollection();
} var schemaElement = LoadRootElement(_host.ResolvePath(sourcePath));
if (schemaElement != null)
{
using (var reader = schemaElement.CreateReader())
{
IList<EdmSchemaError> errors;
var itemCollection = MetadataItemCollectionFactory.CreateEdmItemCollection(new[] { reader }, out errors); ProcessErrors(errors, sourcePath); return itemCollection;
}
}
return new EdmItemCollection();
} public string GetModelNamespace(string sourcePath)
{
ArgumentNotNull(sourcePath, "sourcePath"); if (!ValidateInputPath(sourcePath))
{
return string.Empty;
} var model = LoadRootElement(_host.ResolvePath(sourcePath));
if (model == null)
{
return string.Empty;
} var attribute = model.Attribute("Namespace");
return attribute != null ? attribute.Value : "";
} private bool ValidateInputPath(string sourcePath)
{
if (sourcePath == "$" + "edmxInputFile" + "$")
{
_errors.Add(
new CompilerError(_host.TemplateFile ?? sourcePath, 0, 0, string.Empty,
GetResourceString("Template_ReplaceVsItemTemplateToken")));
return false;
} return true;
} public XElement LoadRootElement(string sourcePath)
{
ArgumentNotNull(sourcePath, "sourcePath"); var root = XElement.Load(sourcePath, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
return root.Elements()
.Where(e => e.Name.LocalName == "Runtime")
.Elements()
.Where(e => e.Name.LocalName == "ConceptualModels")
.Elements()
.Where(e => e.Name.LocalName == "Schema")
.FirstOrDefault()
?? root;
} private void ProcessErrors(IEnumerable<EdmSchemaError> errors, string sourceFilePath)
{
foreach (var error in errors)
{
_errors.Add(
new CompilerError(
error.SchemaLocation ?? sourceFilePath,
error.Line,
error.Column,
error.ErrorCode.ToString(CultureInfo.InvariantCulture),
error.Message)
{
IsWarning = error.Severity == EdmSchemaErrorSeverity.Warning
});
}
} public bool IsLazyLoadingEnabled(EntityContainer container)
{
string lazyLoadingAttributeValue;
var lazyLoadingAttributeName = MetadataConstants.EDM_ANNOTATION_09_02 + ":LazyLoadingEnabled";
bool isLazyLoading;
return !MetadataTools.TryGetStringMetadataPropertySetting(container, lazyLoadingAttributeName, out lazyLoadingAttributeValue)
|| !bool.TryParse(lazyLoadingAttributeValue, out isLazyLoading)
|| isLazyLoading;
}
} public static void ArgumentNotNull<T>(T arg, string name) where T : class
{
if (arg == null)
{
throw new ArgumentNullException(name);
}
} private static readonly Lazy<System.Resources.ResourceManager> ResourceManager =
new Lazy<System.Resources.ResourceManager>(
() => new System.Resources.ResourceManager("System.Data.Entity.Design", typeof(MetadataItemCollectionFactory).Assembly), isThreadSafe: true); public static string GetResourceString(string resourceName)
{
ArgumentNotNull(resourceName, "resourceName"); return ResourceManager.Value.GetString(resourceName, null);
}
private const string ExternalTypeNameAttributeName = @"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName";
public IEnumerable<T> GetItemsToGenerate<T>(IEnumerable<GlobalItem> itemCollection) where T: EdmType
{
return itemCollection
.OfType<T>()
.Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName))
.OrderBy(i => i.Name);
}
#>
生成各种实体类文件的方法很简单,只要保存一下这个EntityOutput.tt文件,各种实体类文件即可应声生成,很爽。
最后生成的文件如蓝线圈圈所示
某个实体扩充类:
// <autogenerated>
// This file was generated by T4 code generator EntityOutput.tt.
// Any changes made to this file manually will be lost next time the file is regenerated.
// </autogenerated> namespace testEF
{
public partial class Show : IEntity
{
public string _ID
{
get
{
return Id.ToString();
}
}
}
}
这个模板文件看起来好复杂,事实上,绝大部分都是自动生成,和拷贝过来的,我自己其实并不懂。
参考文章:
MVC实用架构设计(三)——EF-Code First(3):使用T4模板生成相似代码
http://www.cnblogs.com/guomingfeng/p/mvc-ef-t4.html
EF架构~终于实现了Update方法的统一
http://www.cnblogs.com/lori/archive/2011/07/25/2115982.html
EF学习笔记——生成自定义实体类的更多相关文章
- 【EF框架】EF DBFirst 快速生成数据库实体类 Database1.tt
现有如下需求,数据库表快速映射到数据库实体类 VS给出的两个选择都有问题,并不能实现,都是坑啊 EF .x DbContext 生成器 EF .x DbContext 生成器 测试结果如下 生成文件 ...
- 转:C#制作ORM映射学习笔记一 自定义Attribute类
之前在做unity项目时发现只能用odbc连接数据库,感觉非常的麻烦,因为之前做web开发的时候用惯了ORM映射,所以我想在unity中也用一下ORM(虽然我知道出于性能的考虑这样做事不好的,不过自己 ...
- PythonI/O进阶学习笔记_4.自定义序列类(序列基类继承关系/可切片对象/推导式)
前言: 本文代码基于python3 Content: 1.python中的序列类分类 2. python序列中abc基类继承关系 3. 由list的extend等方法来看序列类的一些特定方法 4. l ...
- 修改tt模板让ADO.NET C# POCO Entity Generator With WCF Support 生成的实体类继承自定义基类
折腾几天记载一下,由于项目实际需要,从edmx生成的实体类能自动继承自定义的基类,这个基类不是从edmx文件中添加的Entityobject. 利用ADO.NET C# POCO Entity Gen ...
- EF学习笔记(十二):EF高级应用场景
学习总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上篇链接:EF学习笔记(十一):实施继承 本篇原文链接:Advanced Entity Framework Scenari ...
- ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则
ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...
- [转]掌握 ASP.NET 之路:自定义实体类简介 --自定义实体类和DataSet的比较
转自: http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx?mfr=true 发布日期 : ...
- Hadoop学习笔记—5.自定义类型处理手机上网日志
转载自http://www.cnblogs.com/edisonchou/p/4288737.html Hadoop学习笔记—5.自定义类型处理手机上网日志 一.测试数据:手机上网日志 1.1 关于这 ...
- EF学习笔记(十一):实施继承
学习总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上篇链接:EF学习笔记(十) 处理并发 本篇原文链接:Implementing Inheritance 面向对象的世界里, ...
随机推荐
- 阿里云虚拟主机针对恶意频繁攻击式访问造成CPU爆满的解决方法
最近网站CPU经常爆满,到阿里云提交了工单,工程师给我的处理意见: 您好,虚拟主机CPU占用比较高通常这种情况有两种可能: 一是网站应用程序代码逻辑较复杂,或业务架构效率比较低,在请求了某个网 ...
- android Activity实现底部滑动弹出窗口及源码下载地址
在做微信.微博.qq等分享时,一般是点击分享按钮后会从底部弹出滑动窗口,然后选择要分享的社交平台进行分享.今日头条.腾讯新闻等内容App的评论也是从底部滑动弹出输入窗口,进行评论输入的.本篇文章就讲讲 ...
- android接收mjpg-streamer软件视频流
[代码]主要实现代码 package cn.dong.mjpeg; import java.io.InputStream; import java.net.HttpURLConnection; imp ...
- Android开发笔记(9)——初步设置Menu
转载请注明:http://www.cnblogs.com/igoslly/p/6858656.html 初步设置Menu 设置Menu,在ActionBar上添加按钮操作: 在 ...
- Java_Web三大框架之Hibernate+HQL语言基础
12.1 HQL语言基础Hibernate查询语言为HQL(Hibernate Query Language),可以直接使用实体类名及属性.HQL语法类似于SQL,有SQL的关键词如select.fr ...
- MyBatis入门2_增删改查+数据库字段和实体字段不一致情况
本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! 当数据库字段和实体bean中属性不一致时 之前数据库P ...
- mstsc windows7/10远程桌面身份验证错误 要求的函数不受支持
之前好好的能远程桌面连接到服务器,但是今天来就不能连接上了,并提示:身份验证错误.要求的函数不受支持. 猜想可能是Windows又更新了什么鬼,后面查询资料知道是由于CredSSP加密Oracle修正 ...
- Appium使用方法说明
global driver# 元素定位driver.find_element_by_id("id") # id定位driver.find_element_by_name(" ...
- yum插件
参考文章: http://www.linuxfly.org/post/297/ [root@dnstest07.tbc /home/ahao.mah] #rpm -qa |grep yum yum-p ...
- uva253 Cube painting(UVA - 253)
题目大意 输入有三种颜色判断两个骰子是否相同 思路(借鉴) ①先用string输入那12个字符,然后for出两个骰子各自的字符串 ②这里用的算法是先找出第一个的三个面与第二个的六个面去比较,如果找到相 ...