七色花基本权限系统(5)- 实体配置的使用和利用T4自动生成实体配置

在前面的章节里,用户表的结构非常简单,没有控制如何映射到数据库。通常,需要对字段的长度、是否可为空甚至特定数据类型进行设置,因为EntityFramework的默认映射规则相对而言比较简单和通用。在这篇日志里,将演示如何对数据实体进行映射配置,并利用T4模板自动创建映射配置类文件。

配置方式

EntityFramework的实体映射配置有2种。

第一种是直接在实体类中以特性的方式进行控制,这些特性有部分是EF实现的,也有部分是非EF实现的。也就是说,在数据实体层不引用EF的情况下,只能使用不全的特性对实体映射进行控制。这种方式有2个明显的弊端:实体类没有尽可能地简单,数据实体层需要引用EF。

第二种是通过EF提供的特定接口进行控制。这种控制方式将完全通过EF提供的配置API,能保证数据实体的干净和独立,并且将映射配置独立出来,便于维护。

映射配置

毫无疑问,这里将采用第二种配置方式。

配置信息是要传递给EF数据上下文的,并且需要引用EF,因此实体配置可以直接建立在数据核心层(S.Framework.DataCore)中。在EntityFramework文件夹下建立新的文件夹,名称Configurations。

需要提醒的是,在数据实体中,我们通过“不同名称的一级文件夹”对不同数据库的实体进行了隔离,在创建EF数据库上下文时,也用同样的名称作为前缀。因此,在实现实体配置时我们也需要进行区分,区分的方式也是文件夹隔离——在Configurations文件夹下创建文件夹,名称Master。如下图:

现在开始创建用户实体配置。

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6 using System.Data.Entity.ModelConfiguration;
  7 using System.Data.Entity.ModelConfiguration.Configuration;
  8
  9 using S.Framework.Entity.Master;
 10
 11 namespace S.Framework.DataCore.EntityFramework.Configurations.Master
 12 {
 13     /// <summary>
 14     /// 数据表映射
 15     /// </summary>
 16     public class SysUserConfiguration : EntityTypeConfiguration<SysUser>
 17     {
 18         /// <summary>
 19         /// 数据表映射构造函数
 20         /// </summary>
 21         public SysUserConfiguration()
 22         {
 23             SysUserConfigurationAppend();
 24         }
 25
 26         /// <summary>
 27         /// 数据映射
 28         /// </summary>
 29         public void SysUserConfigurationAppend()
 30         {
 31             //设置ID属性非空、最大长度38
 32             //由于EF会自动识别名为ID的属性作为主键(会自动非空),所以其实这里只需要设置最大长度即可
 33             this.Property(p => p.ID).IsRequired().HasMaxLength(38);
 34
 35             //设置UserName属性非空、最大长度100
 36             this.Property(p => p.UserName).IsRequired().HasMaxLength(100);
 37
 38             //设置Password属性非空、最大长度100
 39             this.Property(p => p.Password).IsRequired().HasMaxLength(100);
 40
 41             //设置CreateUser属性非空、最大长度100
 42             this.Property(p => p.CreateUser).IsRequired().HasMaxLength(100);
 43
 44             //设置LastModifyUser属性最大长度100
 45             this.Property(p => p.LastModifyUser).HasMaxLength(100);
 46         }
 47
 48         /// <summary>
 49         /// 将映射配置注册给配置注册器
 50         /// </summary>
 51         /// <param name="configurations">配置注册器对象</param>
 52         public void RegistTo(ConfigurationRegistrar configurations)
 53         {
 54             configurations.Add(this);
 55         }
 56     }
 57 }
 58 

用户实体配置类

可配置的内容还有很多,比如数据精度、字段数据类型等等,请查API。

这里稍微提几条常见的EF对实体属性映射的默认规则,这里以Sql server为例。

值类型(int、bool等)的属性映射到数据库后,字段的数据类型是相应的int、bit等,且不允许为空;

引用类型(好像只有string?)的属性映射到数据库后,字段的数据类型是nvarchar(max),允许为空;

属性名为“ID”或者“实体类名ID”的属性,将自动被识别为主键;

注册配置

创建了实体配置类之后,还需要让EF数据库上下文知道有这个配置。

在MasterEntityContext中的OnModelCreating方法中追加,使该方法变成这样:

  1 /// <summary>
  2 /// 模型配置重写
  3 /// </summary>
  4 /// <param name="modelBuilder">数据实体生成器</param>
  5 protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
  6 {
  7     // 禁用一对多级联删除
  8     modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
  9     // 禁用多对多级联删除
 10     modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
 11     // 禁用表名自动复数规则
 12     modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
 13
 14     new SysUserConfiguration().RegistTo(modelBuilder.Configurations);
 15 }

注册配置类给数据库上下文

一切就绪,可以再创建一次数据库看看效果。

删除原数据库,开启Home控制器下Index中的“测试访问数据库”的代码,运行。

新生成的数据库结构如下图:

可以看到,字段的信息发生了改变。

利用T4自动生成实体配置类

当实体数量过多时,为各个实体创建配置类就变成了体力活。我们可以利用T4模板来偷懒,让它自动创建实体配置里。

VS自带的T4模板,略有不足。请先安装2个关于T4的VS插件。

工具 => 扩展和更新,联机搜索Devart T4 Editor和T4 Toolbox for Visual Studio 2013。

需要注意的是,针对不同版本的VS,有不同版本的插件,请选择相应的版本。至于VS2015,听说没有这个插件,那我就不清楚了,还没用上VS2015。若有读者发现VS2015下这2个插件的变化还望留言告知。

在EntityFramework文件夹下创建文件夹,名称T4,如下图:

装了2个插件之后,添加新项时会增加一个新的类型“T4 Toolbox”,我们将用Template文件创建模板,再用Script文件创建执行器。此处,我们先创建一个用于表示“实体配置类”的模板。如下图:

模板代码如下:

  1 <#+
  2 // <copyright file="Configuration.tt" company="">
  3 //  Copyright © . All Rights Reserved.
  4 // </copyright>
  5 public class Configuration : CSharpTemplate
  6 {
  7     private string _modelName; //实体名称
  8     private string _prefixName; //实体前缀名称,表示不同的数据库
  9     public Configuration(string modelName, string prefixName)
 10     {
 11         _modelName = modelName;
 12         _prefixName = prefixName;
 13     }
 14     public override string TransformText()
 15     {
 16     base.TransformText();
 17 #>
 18 using System;
 19 using System.Data.Entity.ModelConfiguration;
 20 using System.Data.Entity.ModelConfiguration.Configuration;
 21 using S.Framework.Entity.<#= _prefixName #>;
 22 namespace S.Framework.DataCore.EntityFramework.Configurations.<#= _prefixName #>
 23 {
 24     /// <summary>
 25     /// 数据表映射
 26     /// </summary>
 27     public class <#= _modelName #>Configuration : EntityTypeConfiguration<<#= _modelName #>>
 28     {
 29         /// <summary>
 30         /// 数据表映射构造函数
 31         /// </summary>
 32         public <#= _modelName #>Configuration()
 33         {
 34             <#= _modelName #>ConfigurationAppend();
 35         }
 36         /// <summary>
 37         /// 数据映射
 38         /// </summary>
 39         public void <#= _modelName #>ConfigurationAppend()
 40         {
 41         }
 42         /// <summary>
 43         /// 将映射配置注册给配置注册器
 44         /// </summary>
 45         /// <param name="configurations">配置注册器对象</param>
 46         public void RegistTo(ConfigurationRegistrar configurations)
 47         {
 48             configurations.Add(this);
 49         }
 50     }
 51 }
 52 <#+
 53     return this.GenerationEnvironment.ToString();
 54     }
 55 }
 56 #>

实体配置模板文件

T4不是重点,此处不做介绍,有兴趣的读者可以自行查阅资料学习。

模板只是表示“目标文件的格式规则是怎样的”,还需要有一个“以一定条件去执行模板”的生成器。上面已经提到过Script执行器文件,创建一个吧。

执行器文件与模板文件有个明显可视的区别是:

执行器文件可以展开。模板文件的使命就是定义结构和规则,只要定义完成,就没它什么事情了。我们需要关注的是如何去调用模板文件。此处不多展开,直接放出Exec.tt文件代码。

  1 <#@ template language="C#" debug="True" #>
  2 <#@ output extension="cs" #>
  3 <#@ import namespace="System.IO" #>
  4 <#@ import namespace="System.Text" #>
  5 <#@ include file="T4Toolbox.tt" #>
  6 <#@ include file="Configuration.tt" #>
  7 <#
  8
  9     string coreName = "S.Framework", projectName = coreName + ".DataCore";
 10     //当前完整路径
 11     string currentPath = Path.GetDirectoryName(Host.TemplateFile);
 12     //T4文件夹的父级文件夹路径
 13     string projectPath = currentPath.Substring(0, currentPath.IndexOf(@"\T4"));
 14     //解决方案路径
 15     string solutionFolderPath = currentPath.Substring(0, currentPath.IndexOf(@"\" + projectName));
 16
 17     //实体名称和实体所在的数据库标识名称
 18     string modelName= "SysUser", prefixName= "Master";
 19     //目标文件的路径和名称(嵌套Generate文件夹是为了标识T4生成的类文件)
 20     string folderName= @"\Configurations\", fileName= prefixName + @"\Generate\" + modelName + "Configuration.cs";
 21     //执行实体配置模板,自动创建文件
 22     Configuration configuration = new Configuration(modelName, prefixName);
 23     configuration.Output.Encoding = Encoding.UTF8;
 24     string path = projectPath + folderName + fileName;
 25     configuration.RenderToFile(path);
 26 #>
 27 

模板执行器文件

注意,这个文件只要保存就会自动执行,也可以通过右键来运行或调试。

在T4里写代码会有点不适应,智能提示、dll库等都是缺失得非常厉害,需要自己手动import相应的dll才行,有问题多调试,会很快搞定的。

执行Exec.tt之后,我们会发现一个新文件被自动创建了,如下图:

这个自动生成的配置类,按照模板中定义的那样,与底下那个手动创建的配置类是一致的。先不急删除“底下那个手动创建的配置类”,因为此时还有几个问题需要解决。

第一个问题:模板文件既然叫做模板,必然是通用于各实体类的。那么必然无法在模板中指定“每个字段的配置”,因为每个实体类的字段都不同的。这样就导致“自动生成的配置类中并不包含配置”,那怎么解决呢?

第二个问题:在模板执行器文件中,硬编码的方式写死了“要生成的目标实体的名称SysUser”,那岂不是需要在为每个实体生成配置类的时候都需要手动调整代码?

先解决第一个问题。C#中可以通过关键字partial来表示部分的意思,可以用在类中,也可以中在方法中。这个关键字就是解决第一个问题的方式。调整配置类的模板文件,修改2处代码。

把配置类的修饰符public改成partial,再把数据映射方法ConfigurationAppend修改成:

  1 /// <summary>
  2 /// 数据映射
  3 /// </summary>
  4 partial void <#= _modelName #>ConfigurationAppend();

修改后的数据映射方法

重新执行exec.tt。

这样,“T4生成的配置类”和“手动创建的配置类”就存在一部分重复的内容,重复的内容交给T4,在“手动创建的配置类”中只需关注不定的内容。修改“手动创建配置类”,只保留“部分方法即可”,如下:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6
  7 using S.Framework.Entity.Master;
  8
  9 namespace S.Framework.DataCore.EntityFramework.Configurations.Master
 10 {
 11     /// <summary>
 12     /// 数据表映射
 13     /// </summary>
 14     partial class SysUserConfiguration
 15     {
 16         /// <summary>
 17         /// 数据映射
 18         /// </summary>
 19         partial void SysUserConfigurationAppend()
 20         {
 21             //设置ID属性非空、最大长度38
 22             //由于EF会自动识别名为ID的属性作为主键(会自动非空),所以其实这里只需要设置最大长度即可
 23             this.Property(p => p.ID).IsRequired().HasMaxLength(38);
 24
 25             //设置UserName属性非空、最大长度100
 26             this.Property(p => p.UserName).IsRequired().HasMaxLength(100);
 27
 28             //设置Password属性非空、最大长度100
 29             this.Property(p => p.Password).IsRequired().HasMaxLength(100);
 30
 31             //设置CreateUser属性非空、最大长度100
 32             this.Property(p => p.CreateUser).IsRequired().HasMaxLength(100);
 33
 34             //设置LastModifyUser属性最大长度100
 35             this.Property(p => p.LastModifyUser).HasMaxLength(100);
 36         }
 37     }
 38 }
 39 

手动创建的配置类

为了目录结构上的统一,我们把调整文件夹为如下结构:

需要注意的是:配置类的命名空间必须是S.Framework.DataCore.EntityFramework.Configurations.Master,否则关键字partial就没有相应的作用。

现在解决第二个问题。

我们用反射来解决这个问题。思路其实很简单,反射数据实体层,获取每个实体类的名称和数据库标识名称,循环执行配置模板文件。

为了能够准确表示“这个类是数据实体类”,我们添加一个“实体类必须要继承的实体基本类”,这样一来,只需要寻找“继承了实体基本类的类”就可以了。

同时再增加一个“实体通用属性公共类”,用来定义通用的属性,比如创建人、创建时间等字段,减少每个实体类的代码量。

这2个类,先定义在数据实体层根目录中,将来会再做调整。

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6
  7 namespace S.Framework.Entity
  8 {
  9     /// <summary>
 10     /// 所有实体模型必须直接或间接继承此类,T4模板中反射 Entity.dll 时将只识别此类的派生类为实体模型
 11     /// </summary>
 12     public abstract class EntityModelBaseForReflection
 13     {
 14     }
 15 }
 16 

实体模型基本类

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6
  7 namespace S.Framework.Entity
  8 {
  9     public abstract class EntityBaseModel : EntityModelBaseForReflection
 10     {
 11         /// <summary>
 12         /// 获取或设置一个 <see cref="string"/> 值,该值表示实体对象的数据创建者。
 13         /// </summary>
 14         public virtual string CreateUser { get; set; }
 15
 16         /// <summary>
 17         /// 获取或设置一个 <see cref="DateTime"/> 值,该值表示实体对象的数据创建时间。
 18         /// </summary>
 19         public virtual DateTime CreateDate { get; set; }
 20
 21         /// <summary>
 22         /// 获取或设置一个 <see cref="string"/> 值,该值表示实体对象的数据最后修改者。
 23         /// </summary>
 24         public virtual string LastModifyUser { get; set; }
 25
 26         /// <summary>
 27         /// 获取或设置一个 <see cref="DateTime"/> 值,该值表示实体对象的数据最后修改时间。
 28         /// </summary>
 29         public virtual DateTime? LastModifyDate { get; set; }
 30     }
 31 }
 32 

实体模型通用类

这2个类都加上了abstract,表示不能被实例化。

现在,让SysUser实体继承EntityBaseModel,并且删除SysUser中的创建人、创建时间、最后修改人、最后修改时间这4个属性。

然后修改Exec.tt,通过反射来获取实体信息。

  1 <#@ template language="C#" debug="True" #>
  2 <#@ assembly name="System.Core" #>
  3 <#@ output extension="cs" #>
  4 <#@ import namespace="System.IO" #>
  5 <#@ import namespace="System.Text" #>
  6 <#@ import namespace="System.Reflection" #>
  7 <#@ import namespace="System.Linq" #>
  8 <#@ import namespace="System.Collections.Generic" #>
  9 <#@ include file="T4Toolbox.tt" #>
 10 <#@ include file="Configuration.tt" #>
 11 <#
 12
 13     string coreName = "S.Framework", projectName = coreName + ".DataCore", entityProjectName = coreName + ".Entity";
 14     string entityBaseModelName = entityProjectName + ".EntityBaseModel";
 15     string entityBaseModelNameForReflection = entityProjectName + ".EntityModelBaseForReflection";
 16     //当前完整路径
 17     string currentPath = Path.GetDirectoryName(Host.TemplateFile);
 18     //T4文件夹的父级文件夹路径
 19     string projectPath = currentPath.Substring(0, currentPath.IndexOf(@"\T4"));
 20     //解决方案路径
 21     string solutionFolderPath = currentPath.Substring(0, currentPath.IndexOf(@"\" + projectName));
 22
 23     //加载数据实体.dll
 24     string entityFilePath = string.Concat(solutionFolderPath, ("\\"+ entityProjectName +"\\bin\\Debug\\" + entityProjectName + ".dll"));
 25     byte[] fileData = File.ReadAllBytes(entityFilePath);
 26     Assembly assembly = Assembly.Load(fileData);
 27     //反射出实体类,不知道为啥此处不能成功判定“是否继承EntityModelBaseForReflection类”
 28     //因此只能通过名称比较的方式来判定
 29     IEnumerable<Type> modelTypes = assembly.GetTypes().Where(m => m.IsClass && !m.IsAbstract && (m.BaseType.FullName.Equals(entityBaseModelName) || m.BaseType.FullName.Equals(entityBaseModelNameForReflection)));
 30
 31     //循环实体类
 32     List<string> prefixNames = new List<string>();
 33     foreach (Type item in modelTypes)
 34     {
 35         //找 实体文件夹 名称
 36         string tempNamespace= item.Namespace, nameSpaceWithoutProjectName = tempNamespace.Substring(entityProjectName.Length);
 37         if(nameSpaceWithoutProjectName.IndexOf(".") != 0 || nameSpaceWithoutProjectName.LastIndexOf(".") > 0)
 38         { continue; }
 39
 40         //是否直接继承实体基本类
 41         bool purity = item.BaseType.FullName.Equals(entityBaseModelNameForReflection);
 42         //实体所在的数据库标识名称
 43         string targetName = nameSpaceWithoutProjectName.Substring(1);
 44         if(!prefixNames.Any(a => a == targetName)){ prefixNames.Add(targetName); }
 45         //目标文件的路径和名称(嵌套Generate文件夹是为了标识T4生成的类文件)
 46         string fileName= targetName + @"\Generate\" + item.Name + "Configuration.cs";
 47
 48         //配置文件
 49         string folderName= @"\Configurations\";
 50         Configuration configuration = new Configuration(item.Name, targetName);
 51         configuration.Output.Encoding = Encoding.UTF8;
 52         string path = projectPath + folderName + fileName;
 53         configuration.RenderToFile(path);
 54     }
 55 #>
 56 

执行器文件

这里注意一下,由于是通过反射S.Framework.Entity/bin/下的S.Framework.Entity.dll来获取实体信息,因此当新增或移除实体,请先编译S.Framework.Entity,再来运行模板执行器。

既然有了“实体通用属性类EntityBaseModel”,那么就可以确定:继承于EntityBaseModel的实体,都需要配置“创建人、创建时间、最后修改人、最后修改时间”这4个字段。那也加到模板中吧,减少手动要写的代码。

修改Configuration.tt如下:

  1 <#+
  2 // <copyright file="Configuration.tt" company="">
  3 //  Copyright © . All Rights Reserved.
  4 // </copyright>
  5
  6 public class Configuration : CSharpTemplate
  7 {
  8     private string _modelName; //实体名称
  9     private string _prefixName; //实体前缀名称,表示不同的数据库
 10     private bool _purity; //是否为纯净的实体,若为纯净则表示无任何额外属性,不纯净则表示包含“创建、最后修改”等额外属性
 11     public Configuration(string modelName, string prefixName, bool purity)
 12     {
 13         _modelName = modelName;
 14         _prefixName = prefixName;
 15         _purity = purity;
 16     }
 17
 18 	public override string TransformText()
 19 	{
 20 		base.TransformText();
 21 #>
 22
 23 using System;
 24 using System.Data.Entity.ModelConfiguration;
 25 using System.Data.Entity.ModelConfiguration.Configuration;
 26
 27 using S.Framework.Entity.<#= _prefixName #>;
 28
 29 namespace S.Framework.DataCore.EntityFramework.Configurations.<#= _prefixName #>
 30 {
 31 	/// <summary>
 32     /// 数据表映射
 33     /// </summary>
 34     partial class <#= _modelName #>Configuration : EntityTypeConfiguration<<#= _modelName #>>
 35     {
 36         /// <summary>
 37         /// 数据表映射构造函数
 38         /// </summary>
 39         public <#= _modelName #>Configuration()
 40         {
 41             <#= _modelName #>ConfigurationDefault();
 42             <#= _modelName #>ConfigurationAppend();
 43         }
 44
 45         /// <summary>
 46         /// 默认的数据映射
 47         /// </summary>
 48         public void <#= _modelName #>ConfigurationDefault()
 49         {
 50 <#+
 51         if(!this._purity)
 52 {
 53 #>
 54             this.Property(p => p.CreateUser).IsRequired().HasMaxLength(100);
 55
 56             this.Property(p => p.LastModifyUser).HasMaxLength(100);
 57 <#+
 58 }
 59 #>
 60         }
 61
 62         /// <summary>
 63         /// 数据映射
 64         /// </summary>
 65         partial void <#= _modelName #>ConfigurationAppend();
 66
 67         /// <summary>
 68         /// 将映射配置注册给配置注册器
 69         /// </summary>
 70         /// <param name="configurations">配置注册器对象</param>
 71         public void RegistTo(ConfigurationRegistrar configurations)
 72         {
 73             configurations.Add(this);
 74         }
 75     }
 76 }
 77 <#+
 78         return this.GenerationEnvironment.ToString();
 79 	}
 80 }
 81 #>
 82 

修改后的配置模板文件

同时,需要在Exec.tt中增加参数的传递。

  1 Configuration configuration = new Configuration(item.Name, targetName);

修改为

  1 Configuration configuration = new Configuration(item.Name, targetName, purity);

再运行Exec.tt,打开生成的用户配置类,检查正确与否。

验收成果

为了检验T4功能和配置功能,我们添加一个角色实体类。

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6
  7 namespace S.Framework.Entity.Master
  8 {
  9     /// <summary>
 10     /// 角色
 11     /// </summary>
 12     public class SysRole : EntityBaseModel
 13     {
 14         /// <summary>
 15         /// 主键
 16         /// </summary>
 17         public string ID { get; set; }
 18
 19         /// <summary>
 20         /// 名称
 21         /// </summary>
 22         public string Name { get; set; }
 23
 24         /// <summary>
 25         /// 排序号
 26         /// </summary>
 27         public int SortNumber { get; set; }
 28     }
 29 }
 30 

角色实体

注意命名空间!别忘记删除“分类文件夹名System”。

编译S.Framework.Entity,然后去右键运行Exec.tt。得到以下结果:

如果要自定义一些配置,请在Customize文件夹中建立同名同命名空间的角色配置类,注意关键字partial。参照自定义用户配置类。

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6
  7 namespace S.Framework.DataCore.EntityFramework.Configurations.Master
  8 {
  9     partial class SysRoleConfiguration
 10     {
 11         partial void SysRoleConfigurationAppend()
 12         {
 13             this.Property(p => p.ID).IsRequired().HasMaxLength(100);
 14
 15             this.Property(p => p.Name).IsRequired().HasMaxLength(100);
 16         }
 17     }
 18 }
 19 

自定义角色配置类

现在把新实体关联到EF数据库上下文中,在MasterEntityContext中增加属性:

  1 /// <summary>
  2 /// 角色
  3 /// </summary>
  4 public DbSet<SysRole> Roles { get; set; }

同时在OnModelCreating方法中增加对角色配置类的注册:

  1 new SysRoleConfiguration().RegistTo(modelBuilder.Configurations);

删除原数据库,重新跑一下项目,让EF再次创建数据库吧。

下一章节,将实现EntityFramework自动合并/迁移/数据初始化。

时间: 06-02

七色花基本权限系统(5)- 实体配置的使用和利用T4自动生成实体配置的相关文章

七色花基本权限系统(3)- 利用EasyUI进行首页布局

EasyUI EasyUI是基于JQuery库的偏js轻型前端UI框架,不了解的读者可以参考官网地址. 在项目中增加JQuery和EasyUI,并在布局页中引用.为了结构清晰,方便日后维护和升级,可以在Scripts下创建jquery文件夹和jquery-easyui文件夹.这里选择1.11.0的JQuery和1.4.3的EasyUI. 特别说明一下,我已经修复了该版本的几个(只能通过修改源码来修正的)bug,并在updateLog.txt文件中做了修复记录. 图标库 再引入2套通用的图标库,以

七色花基本权限系统(8)- 实现实体层和核心层解耦

经过前面的工作,系统正变得越来越清晰. 现在有一个问题需要解决.当需要额外增加一个数据表时,我们需要做的操作是: 在实体层创建实体并编译实体层 在核心层运行T4 配置实体 将实体对象关联给EF数据库上下文(定义DbSet) 将实体配置注册给EF配置对象 这过于繁琐,最后2个步骤,强行地把实体关联在EF数据库上下文里,导致了两者的耦合.这篇日志将演示如何将最后2个步骤省略,解放EF数据库上下文,不用手动关联实体对象,不用手动注册实体配置. 回顾和解释 最后两步还记得吗? 通过定义DbSet对象将实

七色花基本权限系统(10)- 数据接口的实现

为什么要设计数据接口 首先来看一下3层的主要逻辑:数据层 => 业务层 => 应用层.作为通用的项目模板,其中最可能按需而大变的就是数据层,因为不同的项目,使用的数据库.数据驱动技术,是很有可能不同的.项目A,MsSql+EF(就像我正在演示的),项目B,也用这套模板,但变成了MySql+ADO.NET,那么就要尽可能地维持项目的整洁,减少需要修改的代码的量和范围.最佳的做法自然就是"数据层暴露出接口,业务层不关心数据实现". 要设计哪些接口 凡是数据实现层要暴露给业务逻辑

使用MyBatis Generator自动生成实体、mapper和dao层

通过MyBatis Generator可以自动生成实体.mapper和dao层,记录一下怎么用的. 主要步骤: 关于mybatis从数据库反向生成实体.DAO.mapper: 参考文章:http://www.cnblogs.com/wangkeai/p/6934683.html第一种方式:main方法运行(推荐) 1.在pom.xml中加入插件依赖: 2.写mbgConfiguration.xml文件,jdbc.properties文件 3.写/SSM/src/main/java/main/Ge

Mybatis自动生成实体类、dao接口和mapping映射文件

由于Mybatis是一种半自动的ORM框架,它的工作主要是配置mapping映射文件,为了减少手动书写映射文件,可以利用mybatis生成器,自动生成实体类.dao接口以及它的映射文件,然后直接拷贝到工程中稍微修改就可以直接使用了. 生成器目录如下: 首先进入lib文件夹中,该目录如下: (图上文件下载地址:http://download.csdn.net/detail/qiwei31229/9790909) 主要修改generatorConfig.xml <?xml version="1

C#集合篇,在业务背景下(***产品升级管理):依赖注入,变量声明,三元表达式,常用字符串相关操作方法,ADO.NET,EF机制,T4模板自动生成实体类,ref变量巧用,属性实际运用,唯一性验证

QQ:1187362408 欢迎技术交流和学习 关于系统产品升级报告管理,业务需求: TODO: 1,升级报告管理:依据各县区制定升级报告(关联sAreaCode,给每个地区观看具体升级报告信息) 2,运用的技术:依赖注入,变量声明,三元表达式,常用字符串相关操作方法,ADO.NET,EF机制,T4模板自动生成实体类,ref变量与可null变量巧用,属性实际运用,唯一性验证,url传递中文编码和解码问题 讲解篇:1,服务端aspx,2,服务端后台返回数据(这里采用服务器端程序:aspx.cs)

IDEA——mybatis-generator插件自动生成实体代码(Maven)

利用MyBatis生成器自动生成实体类.DAO接口和Mapping映射文件.  mysql-connector-java-5.1.6-bin.jar mysql驱动包  mybatis-generator-core-1.3.5.jar 自动生成器包 maven 配置mybatis-generator插件 一.pom.xml 两处配置 (1) (2) 二.创建 generatorConfig.xml 配置如下: 1 <?xml version="1.0" encoding=&quo

七色花基本权限系统(4) - 初步使用EntityFramework实现用户登录

这篇日志将演示: 1.利用EF的Code First模式,自动创建数据库 2.实现简单的用户登录(不考虑安全仅仅是密码验证) 为什么选择EntityFramework 第一,开发常规中小型系统,能够提高开发效率. 针对小型系统,ORM提高开发效率那是立竿见影.而且linq+lambda的用户体验非常棒,让代码可读性大大增强.即使把linq写得很烂,小系统也无所谓. 针对中型系统,在对ORM有一定了解并且对linq to entity也掌握一定技巧的基础上,使用ORM还是可以提高开发效率. 第二,

七色花基本权限系统(14)- 实现EntityFramework和Dapper的混搭

Dapper是什么 Dapper是一款轻量级的微ORM,其核心是实现了"将查询结果映射到指定数据模型",因此可以抛开DataSet.DataTable等数据集对象,以强类型的方式使用查询数据结果.Dapper是开源的,它的GitHub地址在这里:https://github.com/StackExchange/dapper-dot-net,本章节中选择1.4.0版本的Dapper下的.NET45下的核心类,点击下载该核心类:SqlMapper. 为什么要用Dapper来配合Entity