码迷,mamicode.com
首页 > Web开发 > 详细

Farseer.net轻量级开源框架 V1.x 入门篇:表实体类映射

时间:2015-06-10 12:04:13      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:

导航

目   录:Farseer.net轻量级开源框架 目录

上一篇:Farseer.net轻量级开源框架 V1.x 入门篇:数据库配置及其它配置文件

下一篇:Farseer.net轻量级开源框架 V1.x 入门篇:表的数据操作

前言

  上文讲述了数据库配置及其它配置文件的使用,搭建好数据库的链接方式了,接下来就是数据库中的表与实体类的关联了(映射)。

  在V1.x中,新增了视图、存储过程的映射。在以往的解决方案中,视图是当成”表“来操作的。

  但是我们的视图通常只是为了方便查询而建的。而表支持写操作。会显的很不入调(当然MSSQL的视图也是支持写的,但是这里的视图映射是为了只读视图而来的)

 

  其次,存储过程也支持实体类映射。这是这个版本的一个小创新点。以往我们调用存储过程时,只能在逻辑段里手动写参数名称、存储过程名称。

  这给我们带来了维护灾难,同时最重要的是不支持硬编码方式也是很不优雅的。在新版中实现了这一支持。

  

  Context上下文

  在前面,我们讲到有表、视图、存储过程的映射。那么他们分别对应着:TableContextViewContextProcContext(类似于EntityFramework中的DbContext),同时他们均继承了BaseContext基类

TableContext 表上下文

  表的容器,在实体类中必须继承它,与此同时它的各个表由TableSet封装。

 1 namespace Demo.PO
 2 {
 3     [Context()]
 4     public class Table : TableContext<Table>
 5     {
 6         [Set(Name = "Members_User")]
 7         public TableSet<UserVO> User { get; set; }
 8 
 9         [Set(Name = "Members_Role")]
10         public TableSet<UserRoleVO> UserRole { get; set; }
11     }
12 }

  TableSet表操作类:针对数据库表提供的一系列CURD的操作。被TableSet包含的就是表字段了。

ViewContext 视图上下文

  视图的容器,在实体类中必须继承它,与此同时它的各个视图由ViewSet封装。

 1 namespace Demo.PO
 2 {
 3     [Context(0)]
 4     public class View : ViewContext<View>
 5     {
 6         public View() : base(0) { }
 7 
 8         [Set(Name = "View_Account")]
 9         public ViewSet<AccountVO> Account { get; set; }
10     }
11 }

  ViewSet视图操作类:针对数据库视图提供的一系列查询的操作。被ViewSet包含的就是视图字段了。

ProcContext 存储过程上下文

  存储过程的容器,在实体类中必须继承它,与此同时它的各个存储过程由ProcSet封装。

 1 namespace Demo.PO
 2 {
 3     [Context(0)]
 4     public class Proc : ProcContext<Proc>
 5     {
 6         [Set(Name = "sp_Info_User")]
 7         public ProcSet<InfoUserVO> InfoUser { get; set; }
 8 
 9         [Set(Name = "sp_Insert_User")]
10         public ProcSet<InsertUserVO> InsertUser { get; set; }
11 
12         [Set(Name = "sp_List_User")]
13         public ProcSet<ListUserVO> ListUser { get; set; }
14 
15         [Set(Name = "sp_Value_User")]
16         public ProcSet<ValueUserVO> ValueUser { get; set; }
17     }
18 }

  ProcSet存储过程操作类:针对数据库表提供的一系列执行的操作。被ProcSet包含的就是存储过程字段了。这里有点特殊的是,除了是查询的结果集的映射外,包含了参数传入的映射,并且区分in/out,后面会讲到。

VO实体类

4、表实体类:

 1 public class UserVO : IEntity<int?>
 2 {
 3     /// <summary> 用户ID </summary>
 4     [Field(IsPrimaryKey = true)]
 5     public int? ID { get; set; }
 6     /// <summary> 用户名 </summary>
 7     [Field()]
 8     public string UserName { get; set; }
 9     /// <summary> 密码 </summary>
10     public string PassWord { get; set; }
11     /// <summary> 会员类型 </summary>
12     public eumGenderType? GenderType { get; set; }
13     /// <summary> 登陆次数 </summary>
14     public int? LoginCount { get; set; }
15     /// <summary> 登陆IP </summary>
16     public string LoginIP { get; set; }
17     /// <summary> 登陆IP </summary>
18     [Field(Name = "getdate()")]
19     public DateTime? GetDate { get; set; }
20     /// <summary> 创建时间 </summary>
21     public DateTime? CreateAt { get; set; }
22 }

  可以看到,我们具体的实体,其实是一个POCO的实体

  没错,在V1.x中,框架的一个改变也是为了减轻实体的”负担“,也让框架更加轻量级,而不是侵入式的。

 

  这里重点说下[Field(Name = "getdate()")]

  在后面我们会讲到Field.Name 是显示的告诉框架这个类属性绑定数据库中对应的表字段名称。

  熟悉MSSQL朋友知道,getdate()并不是字段名称,则是MSSQL提供的函数。框架对此也是支持的。

  举个例子,表有两个字段,A、B 都是int类型,

  我们用SQL对A、B的值相加后进行排序是很容易实现的。

  而通过框架,我们可以定义一个类属性,然后Field.Name = "A+B" ,这样我们在排序时,就按照普通的字段进行Desc(o=>o.变量)就可以了。

 

  另外这里继承了IEntity,如前面文章说到的,是为了支持提供的扩展。我们看看IEntity的接口代码吧:

 1 namespace FS.Core.Infrastructure
 2 {
 3     /// <summary> 通过实体类的继承后,后续Set、扩展方法提供针对主键的Where条件 </summary>
 4     /// <typeparam name="T"></typeparam>
 5     public interface IEntity<T>
 6     {
 7         /// <summary> 主键ID </summary>
 8         T ID { get; set; }
 9     }
10 
11     /// <summary> 通过实体类的继承后,后续Set、扩展方法提供针对主键的Where条件(默认为int?) </summary>
12     public interface IEntity : IEntity<int?> { }
13 }

  接口只有一个属性ID,大部份,我们的表都有一个主键。这个主键是自动标识的。

  继承它后,框架提供了一Where条件自动转换的支持:

 1         /// <summary>
 2         ///     对List进行分页
 3         /// </summary>
 4         /// <typeparam name="TEntity">实体类</typeparam>
 5         /// <param name="lst">List列表</param>
 6         /// <param name="IDs">条件,等同于:o=> IDs.Contains(o.ID) 的操作</param>
 7         /// <param name="rpt">Repeater</param>
 8         public static List<TEntity> ToList<TEntity>(this IEnumerable<TEntity> lst, List<int> IDs, Repeater rpt) where TEntity : IEntity
 9 
10         /// <summary>
11         ///     通用的分页方法(多条件)
12         /// </summary>
13         /// <param name="ts">TableSet</param>
14         /// <param name="rpt">Repeater带分页控件</param>
15         /// <typeparam name="TEntity">实体类</typeparam>
16         public static List<TEntity> ToList<TEntity>(this TableSet<TEntity> ts, Repeater rpt) where TEntity : class, IEntity, new()
17 
18         /// <summary>
19         ///     获取下一条记录
20         /// </summary>
21         /// <param name="ID">当前ID</param>
22         /// <param name="ts">TableSet</param>
23         /// <typeparam name="TEntity">实体类</typeparam>
24         public static TEntity ToNextEntity<TEntity>(this TableSet<TEntity> ts, int? ID) where TEntity : class, Core.Infrastructure.IEntity, new()
25         {
26             return ts.Where(o => o.ID > ID).Asc(o => o.ID).ToEntity();
27         }
28 
29         /// <summary>
30         ///     获取上一条记录
31         /// </summary>
32         /// <param name="ID">当前ID</param>
33         /// <param name="ts">TableSet</param>
34         /// <typeparam name="TEntity">实体类</typeparam>
35         public static TEntity ToPreviousEntity<TEntity>(this TableSet<TEntity> ts, int? ID) where TEntity : class, Core.Infrastructure.IEntity, new()
36         {
37             return ts.Where(o => o.ID < ID).Desc(o => o.ID).ToEntity();
38         }
39         /// <summary>
40         ///     获取下一条记录
41         /// </summary>
42         /// <param name="ID">当前ID</param>
43         /// <param name="ts">TableSet</param>
44         /// <typeparam name="TEntity">实体类</typeparam>
45         public static TEntity ToNextEntity<TEntity>(this ViewSet<TEntity> ts, int? ID) where TEntity : class, Core.Infrastructure.IEntity, new()
46         {
47             return ts.Where(o => o.ID > ID).Asc(o => o.ID).ToEntity();
48         }
49 
50         /// <summary>
51         ///     获取上一条记录
52         /// </summary>
53         /// <param name="ID">当前ID</param>
54         /// <param name="ts">TableSet</param>
55         /// <typeparam name="TEntity">实体类</typeparam>
56         public static TEntity ToPreviousEntity<TEntity>(this ViewSet<TEntity> ts, int? ID) where TEntity : class, Core.Infrastructure.IEntity, new()
57         {
58             return ts.Where(o => o.ID < ID).Desc(o => o.ID).ToEntity();
59         }

  当然这里没办法贴出所有的扩展方法来,但让大家知道它的目的就是让我们经常操作的:o.ID == x 、o=> IDs.Contains(o.ID) 这些操作变的更加方便,不需要手动敲代码完成。

 

5、视图实体类:

 1 public class AccountVO
 2 {
 3     /// <summary> 用户ID </summary>
 4     public int? ID { get; set; }
 5     /// <summary> 用户名 </summary>
 6     public string Name { get; set; }
 7     /// <summary> 密码 </summary>
 8     public string Pwd { get; set; }
 9     /// <summary> 登陆IP </summary>
10     [Field(Name = "getdate()")]
11     public string GetDate { get; set; }
12 }

  这里与表是相同的,就不重复的细述了。

 

6、存储过程实体类:

 1 public class InsertUserVO 
 2 {
 3     /// <summary> 用户ID </summary>
 4     [Field(IsOutParam = true)]
 5     public int? ID { get; set; }
 6     /// <summary> 用户名 </summary>
 7     [Field(IsInParam = true)]
 8     public string UserName { get; set; }
 9     /// <summary> 密码 </summary>
10     [Field(IsInParam = true)]
11     public string PassWord { get; set; }
12 }

  存储过程与表、视图的区别比较大。在上面代码中,看到使用了IsOutParamIsInParam的特性。标记后,在执行存储过程时,会根据这些标记生成SQL参数化。传入到存储过程中。

  与此同时,如果该条存储过程执行后,会返回数据列表时,也会对应的返回当前这个实体列表。就根据我们对表进行查询时一样。

  通过存储过程的映射,我们不需要每次调用时手动指定他们了。让我们存储过程也能ORM了。

  技术分享
  以上代码在Demo中。大家可以直接在源代码里面去查找

FieldAttribute特性介绍

7、我们先来介绍第一个特性:字段的映射

  [FieldAttribute]特性目的是告诉框架,当前的这个类属性与数据库的表字段是如何关联在一起的。比如显式的指定表字段的名称。

  我们先来看下面的表格:

序号 变量 注释 类型 适用范围 说明
1 Name 数据库字段名称 string 全部

指定表字段、视图字段名称、存储过程参数的名称、数据库函数

未显示指定时,默认使用当前的类属性名称作为缺省名称

2 IsPrimaryKey 是否为数据库主键 bool TableContext

默认:false

设为:true 并且该变量赋了值是:Insert操作,在MSSQL里,会启用SET IDENTITY_INSERT设置,在Update时,会转换成条件,并去掉赋值。

比如:Table.Data.User.Update(new User{ ID=1,Name="xxx"));  

会被转换成:Table.Data.User.Where(o=>o.ID == 1).Update(new User{ Name="xxx"));

3 InsertStatusType 插入时字段状态

StatusType

枚举类型

TableContext

默认:CanWrite

设为:ReadOnly时,在对应的插入或者更新时,该赋值会被过滤掉(忽略)

设为:ReadCondition时,在对应的插入或者更新时,该赋值会被转换成 == 条件。同时过滤掉赋值(忽略)

这个特性运用的好,对我们编写代码时,可以省去很多Where(o=>o.ID == 1)这种写法,以及安全保护。(禁止被更新,即时赋了值)

4 UpdateStatusType 修改时字段状态 TableContext 
5 IsMap 是否映射到数据库字段中 bool 全部

 默认:true

设为:false 将不映射数据库

6 IsOutParam 指示字段是否为存储过程中输出的参数 bool ProcContext

 默认:false

设为:true 将作为SQL参数值传入,并配合Name声明参数名称,与InParam区别是Out在数据库存储过程中也要声明为该变量是out 即在存储过程中改变时,会将值返回来

7 IsInParam 指示字段是否为存储过程中输入的参数 bool ProcContext  

 默认:false

设为:true 将作为SQL参数值传入,并配合Name声明参数名称

 

SetAttribute特性介绍

  目前只有一个Name属性。

序号 变量 注释 类型 适用范围 说明
 1  Name  表名称、视图名称、存储过程名称  string  全部  

指定表、视图、存储过程的名称

未显示指定时,默认使用当前的类名称作为缺省名称

 

ContextAttribute特性介绍

  目前只有一个Name属性。

序号 变量 注释 类型 适用范围 说明
 1  ConnStr  设置数据库连接字符串  string  全部  

这里跟前面说到的数据库配置里的元素很多相同,就不重复在细述了。

ConnStr未赋值时,框架默认为数据库配置索引项第一项,即如果不是想要动态的情况下,不需要指定这个特性。

可能有时候我们不需要在配置项里保存数据库的信息。那可以在直接在这里进行显示设置。(也可以使用索引的哦)

 1  DataType  设置数据库类型  DataBaseType  全部
 1  DataVer  设置数据库版本  string  全部
 1  CommandTimeout  设置数据库执行T-SQL时间,单位秒默认是30秒  int  全部

  

在这里值得要说的是,除了用这里的数据库配置环境外,还可以通过BaseContext的构造函数来指定:

    public abstract class BaseContext : IDisposable
    {
        /// <summary>
        /// 使用DB特性设置数据库信息
        /// </summary>
        protected BaseContext()
        {
            ContextMap = CacheManger.GetContextMap(this.GetType());
            DataBase = new DbExecutor(ContextMap.ContextProperty.ConnStr, ContextMap.ContextProperty.DataType, ContextMap.ContextProperty.CommandTimeout);
        }

        /// <summary>
        /// 通过数据库配置,连接数据库
        /// </summary>
        /// <param name="dbIndex">数据库选项</param>
        protected BaseContext(int dbIndex) : this(CacheManger.CreateConnString(dbIndex), DbConfigs.ConfigEntity.DbList[dbIndex].DataType, DbConfigs.ConfigEntity.DbList[dbIndex].CommandTimeout) { }

        /// <summary>
        /// 通过自定义数据链接符,连接数据库
        /// </summary>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="dbType">数据库类型</param>
        /// <param name="commandTimeout">SQL执行超时时间</param>
        protected BaseContext(string connectionString, DataBaseType dbType = DataBaseType.SqlServer, int commandTimeout = 30)
        {
            DataBase = new DbExecutor(connectionString, dbType, commandTimeout);
            ContextMap = CacheManger.GetContextMap(this.GetType());
        }
}

   下面看下如何调用的:

 1 [Context()]
 2 public class Table : TableContext<Table>
 3 {
 4     /// <summary>
 5     /// 指定数据库配置项
 6     /// </summary>
 7     public Table() : base(0) { }
 8 
 9     [Set(Name = "Members_User")]
10     public TableSet<UserVO> User { get; set; }
11 
12     [Set(Name = "Members_Role", IsCache = true)]
13     public TableSet<UserRoleVO> UserRole { get; set; }
14 }

   我们通过显示的指定索引即可。但这通常是用在动态配置情况下才会用到。一般的,如果你要显示的时候,通常是通过特性来实现的,特性也支持数据库配置索引:

 1 /// <summary>
 2 /// 指定数据库配置项
 3 /// </summary>
 4 [Context(0)]
 5 public class Table : TableContext<Table>
 6 {
 7     [Set(Name = "Members_User")]
 8     public TableSet<UserVO> User { get; set; }
 9 
10     [Set(Name = "Members_Role", IsCache = true)]
11     public TableSet<UserRoleVO> UserRole { get; set; }
12 }

  也可以这样来定义,特性传入的值必须是常量,意味着我们无法”动态“改变。

总结

  相信通过上文的说明,大家知道如何进行数据库的映射了。

  今天这篇与昨天的,都是环境搭建过程而已。

  到了下一篇,就开始讲解实质性的数据库操作了。希望给大家带来惊喜!

导航

目   录:Farseer.net轻量级开源框架 目录

上一篇:Farseer.net轻量级开源框架 V1.x 入门篇:数据库配置及其它配置文件

下一篇:Farseer.net轻量级开源框架 V1.x 入门篇:表的数据操作

广告时间

QQ群:116228666 (Farseer.net开源框架交流) 请注明:Farseer.Net

Farseer.Net是一款ORM框架 + 常用工具 + 扩展集合。

Farseer 寓意:先知、预言家 通常在某些场合时,提供计谋、策略。也希望该框架能给大家提供最大化的便捷。

ORM:其英文全称是:Object(对象) Relational(关系) Mapping(映射)

Farseer.Net的目标是:快速上手、快速开发、简单方便。

1 Table.Data.User.Where(o=>o.ID == 1).ToEntity();
2 Table.Data.User.Where(o=>o.ID > 1).ToList();
3 Table.Data.User.Where(o=>o.ID != 0).Delete();
4 Table.Data.User.Where(o=>o.ID != 0).AddUp(o=>o.LoginCount, 1);
5 Table.Data.User.Where(o=>o.ID == 1).Update(new User{ UserName = "newName" });
6 Table.Data.User.Insert(new User{ UserName = "newName" });

 

Farseer.net轻量级开源框架 V1.x 入门篇:表实体类映射

标签:

原文地址:http://www.cnblogs.com/steden/p/4555262.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!