本文转自:http://www.cnblogs.com/guomingfeng/p/mvc-ef-t4.html

〇、目录

一、前言

二、工具准备

三、T4代码生成预热

  (一) 单文件生成:HelloWorld.cs

  (二) 多文件生成

四、生成数据层实体相关相似代码

  (一) 生成准备

  (二) 生成实体相关相似代码

  1. 生成实体映射配置类
  2. 生成实体仓储接口
  3. 生成实体仓储实现

五、源码获取

系列导航

一、前言

  经过前面EF的《第一篇》与《第二篇》,我们的数据层功能已经较为完善了,但有不少代码相似度较高,比如负责实体映射的 EntityConfiguration,负责仓储操作的IEntityRepository与EntityRepository。而且每添加一个实体类型,就要手动去添加一套相应的代码,也是比较累的工作。如果能有一个根据实体类型自动生成这些相似度较高的代码的解决方案,那将会减少大量的无聊的工作。

  VS提供的“文本模板”(俗称T4)功能,就是一个较好的解决方案。要添加一个实体类型,只要把实体类型定义好,然后运行一下定义好的T4模板,就可以自动生成相应的类文件。

二、工具准备

  为了更好的使用 T4模板 功能,我们需要给VS安装如下两个插件:

  • Devart T4 Editor:为VS提供智能提示功能。
  • T4 Toolbox:在生成多文件时很有用。

三、T4代码生成预热

(一) 单文件生成:HelloWorld.cs

  下面,我们先来体验一个最简单的T4代码生成功能,输出一个最简单的类文件。

  首先,在 GMF.Demo.Core.Data中 添加一个名为 T4 的文件夹,用于存放生成本工程内的代码的T4模板文件。并在其中添加一个名为 HelloWorld.tt的“文本模板”的项。

  HelloWorld.tt定义如下:

 1 <#@ template debug="false" hostspecific="false" language="C#" #>
 2 <#@ assembly name="System.Core" #>
 3 <#@ import namespace="System.Linq" #>
 4 <#@ import namespace="System.Text" #>
 5 <#@ import namespace="System.Collections.Generic" #>
 6 <#@ output extension=".cs" #>
 7 using System;
 8
 9 namespace GMF.Demo.Core.Data.T4
10 {
11     public class HelloWorld
12     {
13         private string _word;
14
15         public HelloWorld(string word)
16         {
17             _word = word;
18         }
19     }
20 }

  直接保存文件(T4的生成将会在保存模板,模板失去焦点等情况下自动触发生成。),将会在模板的当前位置生成一个同名的类文件:

  HelloWorld.cs的内容如下:

 1 using System;
 2
 3 namespace GMF.Demo.Core.Data.T4
 4 {
 5     public class HelloWorld
 6     {
 7         private string _word;
 8
 9         public HelloWorld(string word)
10         {
11             _word = word;
12         }
13     }
14 }

  这样,我们的HelloWorld之旅就结束了,非常简单。

(二) 多文件生成

  当前位置方案的方案只能生成如下所示的代码:

  生成的文件会与T4模板在同一目录中,这里就不详述了,可以参考 蒋金楠 一个简易版的T4代码生成"框架" 。

  本项目的多文件需要生成到指定文件夹中,但又想对T4模板进行统一的管理,T4文件夹里放置T4模板文件,但生成的映射文件EntityConfiguration将放置到文件夹Configurations中,仓储操作的文件IEntityRepository与EntityRepository将放置到Repositories文件夹中。且生成的代码文件应能自动的添加到解决方案中,而不是只是在文件夹中存在。

  要实现此需求,一个简单的办法就是通过 T4 Toolbox 来进行生成。想了解 T4 Toolbox 的细节,可以自己使用 ILSpy 来对 T4Toolbox.dll 文件进行反编译来查看源代码,如果是通过 T4 Toolbox 是通过VS的插件来安装的,将在“C:\Users\Administrator\AppData\Local\Microsoft\VisualStudio\11.0\Extensions\dca4f0lt.jdx”文件夹中(我的机器上)。下面,我们直接进行多文件生成的演示。

  首先,添加一个名为 HelloWorldTemplate.tt 的 T4 Toolbox 的代码模板。

  此模板将继承于 T4 Toolbox 的 CSharpTemplate 类:

 1 <#+
 2 // <copyright file="HelloWorldTemplate.tt" company="郭明锋@中国">
 3 //  Copyright © 郭明锋@中国. All Rights Reserved.
 4 // </copyright>
 5
 6 public class HelloWorldTemplate : CSharpTemplate
 7 {
 8     private string _className;
 9
10     public HelloWorldTemplate(string className)
11     {
12         _className = className;
13     }
14
15     public override string TransformText()
16     {
17 #>
18 using System;
19
20 namespace GMF.Demo.Core.Data.T4
21 {
22     public class <#=_className #>
23     {
24         private string _word;
25
26         public <#=_className #>(string word)
27         {
28             _word = word;
29         }
30     }
31 }
32 <#+
33         return this.GenerationEnvironment.ToString();
34     }
35 }
36 #>

  模板类中定义了一个 className 参数,用于接收一个表示要生成的类名的值。所有生成类的代码都以字符串的形式写在重写的 TransformText 方法中。

  再定义一个T4模板文件 HelloWorldMulti.tt,用于调用 上面定义的代码模板进行代码文件的生成。

 1 <#@ template debug="false" hostspecific="false" language="C#" #>
 2 <#@ assembly name="System.Core" #>
 3 <#@ import namespace="System.IO" #>
 4 <#@ import namespace="System.Linq" #>
 5 <#@ import namespace="System.Text" #>
 6 <#@ import namespace="System.Collections.Generic" #>
 7 <#@ include file="T4Toolbox.tt" #>
 8 <#@ include file="HelloWorldTemplate.tt" #>
 9 <#
10     string curPath = Path.GetDirectoryName(Host.TemplateFile);
11     string destPath = Path.Combine(curPath, "outPath");
12     if(!Directory.Exists(destPath))
13     {
14         Directory.CreateDirectory(destPath);
15     }
16     string[] classNames = new[]{"HelloWorld1", "HelloWorld2", "HelloWorld3"};
17     foreach(string className in classNames)
18     {
19         HelloWorldTemplate template = new HelloWorldTemplate(className);
20         string fileName = string.Format(@"{0}\{1}.cs", destPath, className);
21         template.Output.Encoding = Encoding.UTF8;
22         template.RenderToFile(fileName);
23     }
24  #>

  以上是整个T4模板的执行方,在执行方中,要引用所有需要用到的类库文件,命名空间,包含的模板文件等。

  最后,文件的生成是调用 T4 Toolbox 的Template基类中定义的 RenderToFile(string filename)方法来生成各个文件的,输入的参数为生成文件的文件全名。在这里,生成将如下所示:

  outPPath文件夹中生成了 HelloWorld1.cs、HelloWorld2.cs、HelloWorld3.cs 文件,而 HelloWorldMulti.tt 所在文件夹中也会生成一个空的 HelloWorldMulti.cs 类文件。

四、生成数据层实体相关相似代码

(一) 生成准备

  我们的生成代码是完全依赖于业务实体的,所以,需要有一个类来对业务实体的信息进行提取封装。

 1 namespace GMF.Component.Tools.T42 {3     /// <summary>4     /// T4实体模型信息类5     /// </summary>6     public class T4ModelInfo7     {8         /// <summary>9         /// 获取 模型所在模块名称
10         /// </summary>
11         public string ModuleName { get; private set; }
12
13         /// <summary>
14         /// 获取 模型名称
15         /// </summary>
16         public string Name { get; private set; }
17
18         /// <summary>
19         /// 获取 模型描述
20         /// </summary>
21         public string Description { get; private set; }
22
23         public IEnumerable<PropertyInfo> Properties { get; private set; }
24
25         public T4ModelInfo(Type modelType)
26         {
27             var @namespace = modelType.Namespace;
28             if (@namespace == null)
29             {
30                 return;
31             }
32             var index = @namespace.LastIndexOf('.') + 1;
33             ModuleName = @namespace.Substring(index, @namespace.Length - index);
34             Name = modelType.Name;
35             var descAttributes = modelType.GetCustomAttributes(typeof(DescriptionAttribute), true);
36             Description = descAttributes.Length == 1 ? ((DescriptionAttribute)descAttributes[0]).Description : Name;
37             Properties = modelType.GetProperties();
38         }
39     }
40 }

  另外,通过模板生成的代码,与我们手写的代码有如下几个区别:

  1. 手写代码可以自由定义,生成代码是根据模板生成的,必然遵守模板定义的规范。
  2. 手写代码的修改可以永久保存,生成代码的修改将会在下次生成后丢失,即生成代码不应该进行修改。

  基于以上几个区别,我提出如下解决方案,来解决生成代码的修改问题

  1. 通过模板生成的类应尽量定义为分部类(partial class),在需要进行修改及扩展的时候可以定义另外的同名分部类来进行修改。
  2. 对于需要外部实现的功能,定义分部方法来对外提供扩展。
  3. 生成代码的类文件命名把扩展名由“.cs”更改为“generated.cs”,以区分生成代码与手写代码文件。

(二) 生成实体相关相似代码

  1. 生成实体映射配置类

  实体映射配置类模板 EntityConfigurationTemplate.tt 定义:

 1 <#+
 2 // <copyright file="EntityConfigurationTemplate.tt" company="郭明锋@中国">
 3 //  Copyright © 郭明锋@中国. All Rights Reserved.
 4 // </copyright>
 5
 6 public class EntityConfigurationTemplate : CSharpTemplate
 7 {
 8     private T4ModelInfo _model;
 9
10     public EntityConfigurationTemplate(T4ModelInfo model)
11     {
12         _model = model;
13     }
14
15     /// <summary>
16     /// 获取 生成的文件名,根据模型名定义
17     /// </summary>
18     public string FileName
19     {
20         get
21         {
22             return string.Format("{0}Configuration.generated.cs", _model.Name);
23         }
24     }
25
26     public override string TransformText()
27     {
28 #>
29 //------------------------------------------------------------------------------
30 // <auto-generated>
31 //     此代码由工具生成。
32 //     对此文件的更改可能会导致不正确的行为,并且如果
33 //     重新生成代码,这些更改将会丢失。
34 //        如存在本生成代码外的新需求,请在相同命名空间下创建同名分部类实现 <#= _model.Name #>ConfigurationAppend 分部方法。
35 // </auto-generated>
36 //
37 // <copyright file="<#= _model.Name #>Configuration.generated.cs">
38 //        Copyright(c)2013 GMFCN.All rights reserved.
39 //        CLR版本:4.0.30319.239
40 //        开发组织:郭明锋@中国
41 //        公司网站:http://www.gmfcn.net
42 //        所属工程:GMF.Demo.Core.Data
43 //        生成时间:<#= DateTime.Now.ToString("yyyy-MM-dd HH:mm") #>
44 // </copyright>
45 //------------------------------------------------------------------------------
46
47 using System;
48 using System.Data.Entity.ModelConfiguration;
49 using System.Data.Entity.ModelConfiguration.Configuration;
50
51 using GMF.Component.Data;
52 using GMF.Demo.Core.Models;
53
54
55 namespace GMF.Demo.Core.Data.Configurations
56 {
57     /// <summary>
58     /// 实体类-数据表映射——<#= _model.Description #>
59     /// </summary>
60     internal partial class <#= _model.Name #>Configuration : EntityTypeConfiguration<<#= _model.Name #>>, IEntityMapper
61     {
62         /// <summary>
63         /// 实体类-数据表映射构造函数——<#= _model.Description #>
64         /// </summary>
65         public <#= _model.Name #>Configuration()
66         {
67             <#= _model.Name #>ConfigurationAppend();
68         }
69
70         /// <summary>
71         /// 额外的数据映射
72         /// </summary>
73         partial void <#= _model.Name #>ConfigurationAppend();
74
75         /// <summary>
76         /// 将当前实体映射对象注册到当前数据访问上下文实体映射配置注册器中
77         /// </summary>
78         /// <param name="configurations">实体映射配置注册器</param>
79         public void RegistTo(ConfigurationRegistrar configurations)
80         {
81             configurations.Add(this);
82         }
83     }
84 }
85 <#+
86         return this.GenerationEnvironment.ToString();
87     }
88 }
89 #>

  生成模板调用方 EntityCodeScript.tt 定义

 1 <#@ template language="C#" debug="True" #>
 2 <#@ output extension="cs" #>
 3 <#@ Assembly Name="System.Core" #>
 4 <#@ Assembly Name="$(SolutionDir)\GMF.Component.Tools\bin\Debug\GMF.Component.Tools.dll" #>
 5 <#@ import namespace="System.IO" #>
 6 <#@ Import Namespace="System.Linq" #>
 7 <#@ Import Namespace="System.Text" #>
 8 <#@ import namespace="System.Reflection" #>
 9 <#@ Import Namespace="System.Collections.Generic" #>
10 <#@ Import Namespace="GMF.Component.Tools" #>
11 <#@ Import Namespace="GMF.Component.Tools.T4" #>
12 <#@ include file="T4Toolbox.tt" #>
13 <#@ include file="Include\EntityConfigurationTemplate.tt" #>
14 <#
15     string currentPath = Path.GetDirectoryName(Host.TemplateFile);
16     string projectPath =currentPath.Substring(0, currentPath.IndexOf(@"\T4"));
17     string solutionPath = currentPath.Substring(0, currentPath.IndexOf(@"\GMF.Demo.Core.Data"));
18
19     string modelFile= Path.Combine(solutionPath, @"GMF.Demo.Core.Models\bin\Debug\GMF.Demo.Core.Models.dll");
20     byte[] fileData= File.ReadAllBytes(modelFile);
21     Assembly assembly = Assembly.Load(fileData);
22     IEnumerable<Type> modelTypes = assembly.GetTypes().Where(m => typeof(Entity).IsAssignableFrom(m) && !m.IsAbstract);
23     foreach(Type modelType in modelTypes)
24     {
25         T4ModelInfo model = new T4ModelInfo(modelType);
26         //实体映射类
27         EntityConfigurationTemplate config = new EntityConfigurationTemplate(model);
28         string path = string.Format(@"{0}\Configurations", projectPath);
29         config.Output.Encoding = Encoding.UTF8;
30         config.RenderToFile(Path.Combine(path, config.FileName));
31     }
32 #>

  调用方通过反射从业务实体程序集 GMF.Demo.Core.Models.dll 中获取所有基类为 Entity 的并且不是抽象类的实体类型信息,再调用模板逐个生成实体配置类文件。

  例如,生成的登录记录信息(LoginLog)的映射文件 LoginLogConfiguration.generated.cs 如下:

 1 //------------------------------------------------------------------------------
 2 // <auto-generated>
 3 //     此代码由工具生成。
 4 //     对此文件的更改可能会导致不正确的行为,并且如果
 5 //     重新生成代码,这些更改将会丢失。
 6 //        如存在本生成代码外的新需求,请在相同命名空间下创建同名分部类实现 LoginLogConfigurationAppend 分部方法。
 7 // </auto-generated>
 8 //
 9 // <copyright file="LoginLogConfiguration.generated.cs">
10 //        Copyright(c)2013 GMFCN.All rights reserved.
11 //        CLR版本:4.0.30319.239
12 //        开发组织:郭明锋@中国
13 //        公司网站:http://www.gmfcn.net
14 //        所属工程:GMF.Demo.Core.Data
15 //        生成时间:2013-06-16 17:45
16 // </copyright>
17 //------------------------------------------------------------------------------
18
19 using System;
20 using System.Data.Entity.ModelConfiguration;
21 using System.Data.Entity.ModelConfiguration.Configuration;
22
23 using GMF.Component.Data;
24 using GMF.Demo.Core.Models;
25
26
27 namespace GMF.Demo.Core.Data.Configurations
28 {
29     /// <summary>
30     /// 实体类-数据表映射——登录记录信息
31     /// </summary>
32     internal partial class LoginLogConfiguration : EntityTypeConfiguration<LoginLog>, IEntityMapper
33     {
34         /// <summary>
35         /// 实体类-数据表映射构造函数——登录记录信息
36         /// </summary>
37         public LoginLogConfiguration()
38         {
39             LoginLogConfigurationAppend();
40         }
41
42         /// <summary>
43         /// 额外的数据映射
44         /// </summary>
45         partial void LoginLogConfigurationAppend();
46
47         /// <summary>
48         /// 将当前实体映射对象注册到当前数据访问上下文实体映射配置注册器中
49         /// </summary>
50         /// <param name="configurations">实体映射配置注册器</param>
51         public void RegistTo(ConfigurationRegistrar configurations)
52         {
53             configurations.Add(this);
54         }
55     }
56 }

  要配置登录信息与用户信息的 N:1 关系,只需要添加一个分部类 LoginLogConfiguration,并实现分类方法 LoginLogConfigurationAppend 即可。

 1 namespace GMF.Demo.Core.Data.Configurations
 2 {
 3     partial class LoginLogConfiguration
 4     {
 5         partial void LoginLogConfigurationAppend()
 6         {
 7             HasRequired(m => m.Member).WithMany(n => n.LoginLogs);
 8         }
 9     }
10 }

  2. 生成实体仓储接口

  实体映射配置类模板 EntityConfigurationTemplate.tt 定义:

 1 <#+
 2 // <copyright file="IEntityRepositoryTemplate.tt" company="郭明锋@中国">
 3 //  Copyright © 郭明锋@中国. All Rights Reserved.
 4 // </copyright>
 5
 6 public class IEntityRepositoryTemplate : CSharpTemplate
 7 {
 8     private T4ModelInfo _model;
 9
10     public IEntityRepositoryTemplate(T4ModelInfo model)
11     {
12         _model = model;
13     }
14
15     /// <summary>
16     /// 获取 生成的文件名,根据模型名定义
17     /// </summary>
18     public string FileName
19     {
20         get
21         {
22             return string.Format("I{0}Repository.generated.cs", _model.Name);
23         }
24     }
25
26     public override string TransformText()
27     {
28 #>
29 //------------------------------------------------------------------------------
30 // <auto-generated>
31 //     此代码由工具生成。
32 //     对此文件的更改可能会导致不正确的行为,并且如果
33 //     重新生成代码,这些更改将会丢失。
34 //       如存在本生成代码外的新需求,请在相同命名空间下创建同名分部类进行实现。
35 // </auto-generated>
36 //
37 // <copyright file="I<#= _model.Name #>Repository.generated.cs">
38 //        Copyright(c)2013 GMFCN.All rights reserved.
39 //        CLR版本:4.0.30319.239
40 //        开发组织:郭明锋@中国
41 //        公司网站:http://www.gmfcn.net
42 //        所属工程:GMF.Demo.Core.Data
43 //        生成时间:<#= DateTime.Now.ToString("yyyy-MM-dd HH:mm") #>
44 // </copyright>
45 //------------------------------------------------------------------------------
46
47 using System;
48
49 using GMF.Component.Data;
50 using GMF.Demo.Core.Models;
51
52
53 namespace GMF.Demo.Core.Data.Repositories
54 {
55     /// <summary>
56     ///   数据访问层接口——<#= _model.Description #>
57     /// </summary>
58     public partial interface I<#= _model.Name #>Repository : IRepository<<#= _model.Name #>>
59     { }
60 }
61
62 <#+
63         return this.GenerationEnvironment.ToString();
64     }
65 }
66 #>

  相应的,在调用方 EntityCodeScript.tt 中添加模板调用代码(如下 11-15 行所示):

 1     foreach(Type modelType in modelTypes)
 2     {
 3         T4ModelInfo model = new T4ModelInfo(modelType);
 4
 5         //实体映射类
 6         EntityConfigurationTemplate config = new EntityConfigurationTemplate(model);
 7         string path = string.Format(@"{0}\Configurations", projectPath);
 8         config.Output.Encoding = Encoding.UTF8;
 9         config.RenderToFile(Path.Combine(path, config.FileName));
10
11         //实体仓储操作接口
12         IEntityRepositoryTemplate irep= new IEntityRepositoryTemplate(model);
13         path = string.Format(@"{0}\Repositories", projectPath);
14         irep.Output.Encoding = Encoding.UTF8;
15         irep.RenderToFile(Path.Combine(path, irep.FileName));
16     }

  生成的登录记录信息仓储操作接口 ILoginLogRepository.generated.cs:

 1 //------------------------------------------------------------------------------
 2 // <auto-generated>
 3 //     此代码由工具生成。
 4 //     对此文件的更改可能会导致不正确的行为,并且如果
 5 //     重新生成代码,这些更改将会丢失。
 6 //       如存在本生成代码外的新需求,请在相同命名空间下创建同名分部类进行实现。
 7 // </auto-generated>
 8 //
 9 // <copyright file="ILoginLogRepository.generated.cs">
10 //        Copyright(c)2013 GMFCN.All rights reserved.
11 //        CLR版本:4.0.30319.239
12 //        开发组织:郭明锋@中国
13 //        公司网站:http://www.gmfcn.net
14 //        所属工程:GMF.Demo.Core.Data
15 //        生成时间:2013-06-16 17:56
16 // </copyright>
17 //------------------------------------------------------------------------------
18
19 using System;
20
21 using GMF.Component.Data;
22 using GMF.Demo.Core.Models;
23
24
25 namespace GMF.Demo.Core.Data.Repositories
26 {
27     /// <summary>
28     ///   数据访问层接口——登录记录信息
29     /// </summary>
30     public partial interface ILoginLogRepository : IRepository<LoginLog>
31     { }
32 }

  如果 IRepository<T> 中定义的仓储操作不满足登录记录仓储操作的需求,只需要添加一个相应的分部接口,在其中进行需求的定义即可。这里当前没有额外的需求,就不需要额外定义了。

  3. 生成实体仓储实现

  实体仓储操作的实现与仓储操作接口类似,这里略过。

  完成生成后,代码结构如下所示:

  如果添加了或者删除了一个实体,只需要重新运行一下调用模板 EntityCodeScript.tt 即可重新生成新的代码。

五、源码获取

  为了让大家能第一时间获取到本架构的最新代码,也为了方便我对代码的管理,本系列的源码已加入微软的开源项目网站 http://www.codeplex.com,地址为:

  https://gmframework.codeplex.com/

  可以通过下列途径获取到最新代码:

  • 如果你是本项目的参与者,可以通过VS自带的团队TFS直接连接到 https://tfs.codeplex.com:443/tfs/TFS17 获取最新代码
  • 如果你安装有SVN客户端(亲测TortoiseSVN 1.6.7可用),可以连接到 https://gmframework.svn.codeplex.com/svn 获取最新代码
  • 如果以上条件都不满足,你可以进入页面 https://gmframework.codeplex.com/SourceControl/latest 查看最新代码,也可以点击页面上的 Download 链接进行压缩包的下载,你还可以点击页面上的 History 链接获取到历史版本的源代码
  • 如果你想和大家一起学习MVC,学习EF,欢迎加入Q群:5008599(群发言仅限技术讨论,拒绝闲聊,拒绝酱油,拒绝广告)
  • 如果你想与我共同来完成这个开源项目,可以随时联系我。

系列导航

  1. MVC实用架构设计(〇)——总体设计
  2. MVC实用架构设计(一)——项目结构搭建
  3. MVC实用架构设计(二)——使用MEF应用IOC
  4. MVC实用架构设计(三)——EF-Code First(1):Repository,UnitOfWork,DbContext
  5. MVC实用架构设计(三)——EF-Code First(2):实体映射、数据迁移,重构
  6. MVC实用架构设计(三)——EF-Code First(3):使用T4模板生成相似代码
  7. MVC实用架构设计(三)——EF-Code First(4):数据查询
  8. MVC实用架构设计(三)——EF-Code First(5):二级缓存
  9. MVC实体架构设计(三)——EF-Code First(6):数据更新
  10. 未完待续。。。
如果您看完本篇文章感觉不错,请点击一下右下角的【推荐】来支持一下博主,谢谢!

作者:郭明锋 出处:http://www.cnblogs.com/guomingfeng

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

[转]MVC实用架构设计(三)——EF-Code First(3):使用T4模板生成相似代码相关推荐

  1. MVC实用架构设计(三)——EF-Code First(1):Repository,UnitOfWork,DbContext

    前言 终于到EF了,实在不好意思,最近有点忙,本篇离上一篇发布已经一个多星期了,工作中的小迭代告一段落,终于有点时间来继续我们的架构设计了,在这里先对大家表示歉意. 其实这段时间我并不是把这个系列给忘 ...

  2. 分布式系统架构设计三十六式之服务治理 - 第一式 - 隔板模式

    导读 日拱一卒,功不唐捐,分享是最好的学习,一个知识领域里的 "道 法 术 器" 这四个境界需要从 微观.中观以及宏观 三个角度来把握.微观是实践,中观讲套路,宏观靠领悟.本系列文 ...

  3. 阿里云域名解析网络和服务架构设计(三) 之阿里云CLB负载均衡

    一.回顾 阿里云域名解析网络和服务架构设计总概览(一)_飞鸽FlyGo的博客-CSDN博客云解析DNS.负载均衡SLB.阿里云ECS服务器.阿里云ECS服务器Nginx代理https://flygo. ...

  4. ASP.NET MVC +EasyUI 权限设计(三)基础模块

    请注明转载地址:http://www.cnblogs.com/arhat 在上一章中呢,我们基本上搭建好了环境,那么本章我们就从基础模块开始写起.由于用户,角色,动作三个当中,都是依赖与动作的,所以本 ...

  5. ef mysql 优化_MySQL性能管理及架构设计(二):数据库结构优化、高可用架构设计、数据库索引优化...

    一.数据库结构优化(非常重要) 1.1 数据库结构优化目的 1.减少数据冗余:(数据冗余是指在数据库中存在相同的数据,或者某些数据可以由其他数据计算得到),注意,尽量减少不代表完全避免数据冗余: 2. ...

  6. iOS架构设计(三)- MVVM

    我是不敢轻易谈MVVM架构设计的 终于在经过前面几篇文章内容的铺垫之后,现在简单说说自己的想法 切记,如果没有kvc kvo的原理知识铺垫,最好去复习一下,否则看过了解,回头就会忘却,不会形成意识 K ...

  7. 敏捷思维- 架构设计中的方法学

    敏捷思维-架构设计中的方法学 目录 1.从方法论看架构设计... 2 2.架构设计的敏捷视图... 7 3.源自需求... 13 4.团队设计... 18 5.简单设计... 24 6.迭代设计... ...

  8. 敏捷思维-架构设计中的方法学

    敏捷思维-架构设计中的方法学 1.    从方法论看架构设计 1.    架构设计的敏捷视图 2.    源自需求 3.    团队设计 4.    简单设计 5.    迭代设计 6.    组合使 ...

  9. .NET Core实战项目之CMS 第九章 设计篇-白话架构设计

    前面两篇文章给大家介绍了我们实战的CMS系统的数据库设计,源码也已经上传到服务器上了.今天我们就好聊聊架构设计,在开始之前先给大家分享一下这几天我一直在听的<从零开始学架构>里面关于架构设 ...

最新文章

  1. 1小时上手MaskRCNN·Keras开源实战 | 深度应用
  2. tomcat-清除缓存
  3. 模板:Prufer序列
  4. 9.数据库中的子查询
  5. ArcEngine开发 退出系统报错
  6. HTML5高层模块不应该依赖于底层模块
  7. 使用Python解析MNIST数据集
  8. 记一次Mysql数据库Kill完之后启动不起来的解决方案
  9. itop 安装时碰到的Missing PHP extension mysqli soap ldap
  10. OKB突破7.2USDT,再创12月新高
  11. maven命令指定配置文件
  12. 应用工具推荐phpStudy(小皮面板)
  13. python培训班怎样收费
  14. java-php-python-ssm特困生服务系统计算机毕业设计
  15. 阿里云ECS添加公网IPV6
  16. Web开发了一个完整精美的聊天室(登录部分引入了Vue技术)
  17. GAMES101笔记_Lec07~09_着色 Shading
  18. 通过 kubeadm 安装 k8s 1.14.1版本(master 单节点版)
  19. Android-UI开发(一)
  20. 万粉博主为CSDN增加粉丝数据分析模块【硬核】

热门文章

  1. 语言抄袭广东工业大学_CUBA出现消极比赛,广东工业大学与江西师范大学被取消成绩...
  2. cad2020 开始_如何设置CAD2020经典模式,原来这么简单,一起来看看
  3. fegin需要实现类_深入理解JVM(六)--虚拟机类加载机制
  4. hdu4862 费用流(不错)
  5. POJ 3461 KMP
  6. 【Java 并发编程】线程锁机制 ( 线程安全 | 锁机制 | 类锁 | 对象锁 | 轻量级锁 | 重量级锁 )
  7. 【Android APT】编译时技术 ( 编译时注解 和 注解处理器 依赖库 )
  8. 【MATLAB】变量 ( 特殊变量和常量 | 关键字 | 调用优先级 | 数值显示格式 )
  9. 【Android 安全】DEX 加密 ( Java 工具开发 | 生成 dex 文件 | Java 命令行执行 )
  10. 【Android 性能优化】应用启动优化 ( 安卓应用启动分析 | ActivityThread 主函数分析 | 应用初始化 | 启动优化项目 )