1. 程式人生 > >EF學習筆記——生成自定義實體類

EF學習筆記——生成自定義實體類

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

使用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 testEFpublic 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 testEFpublic 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


           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述