当把常用的特性填写到POCO实体类时,执行数据库操作时,需要根据实体类上的特性信息进行相应的操作,PetaPoco中的TableInfo和ColumnInfo类就是用来保存实体类上的特性信息。

TableInfo用来保存数据库表的信息,包括TableName,PrimaryKey,主键是否自增字段,使用Oracle数据库时的Sequence名称。

ColumnInfo用来保存数据库表的列信息,包括ColumnName,是否结果列(不用更新数据库),数据库列类型是否转换为UTC时间、更新模板和插入模板。

  通过POCO实体类获取到其对应的数据库表和数据库列的信息,就可以使用这些信息对数据库表执行增删改查的操作。

TableInfo包括一个静态方法,参数为POCO实体类的Type对象,从该对象上获取自定义特性信息来初始化TableInfo实例。

     /// <summary>
/// POCO实体类对应的数据库表信息
/// </summary>
public class TableInfo
{
/// <summary>
/// 数据库表名
/// </summary>
public string TableName { get; set; } /// <summary>
/// 数据库表主键
/// </summary>
public string PrimaryKey { get; set; } /// <summary>
/// 主键是否自增
/// </summary>
public bool AutoIncrement { get; set; } /// <summary>
/// Oracle数据自增主键对应的Sequence名称
/// </summary>
public string SequenceName { get; set; } /// <summary>
/// 从POCO实体类的特性上初始化TableInfo实例
/// </summary>
public static TableInfo FromPoco(Type t)
{
TableInfo ti = new TableInfo();
//从TableNameAttribute上获取数据表名称,若不存在则使用POCO实体类的名称
var a = t.GetCustomAttributes(typeof(TableNameAttribute), true);
ti.TableName = a.Length == ? t.Name : (a[] as TableNameAttribute).Value; //从PrimaryKeyAttribute上获取数据库表主键名称
a = t.GetCustomAttributes(typeof(PrimaryKeyAttribute), true);
ti.PrimaryKey = a.Length == ? null : (a[] as PrimaryKeyAttribute).Value;
ti.SequenceName = a.Length == ? null : (a[] as PrimaryKeyAttribute).SequenceName;
ti.AutoIncrement = a.Length == ? false : (a[] as PrimaryKeyAttribute).AutoIncrement;
//若不存在PrimaryKeyAttribute,则查找实体类属性中名称为“id"或者实体类名称+“id"或者“_id"的类属性。
if (string.IsNullOrEmpty(ti.PrimaryKey))
{
var prop = t.GetProperties().FirstOrDefault(p =>
{
if (p.Name.Equals("id", StringComparison.OrdinalIgnoreCase))
return true;
if (p.Name.Equals(t.Name + "id", StringComparison.OrdinalIgnoreCase))
return true;
if (p.Name.Equals(t.Name + "_id", StringComparison.OrdinalIgnoreCase))
return true;
return false;
});
if (prop != null)
{
ti.PrimaryKey = prop.Name;
ti.AutoIncrement = prop.PropertyType.IsValueType;
}
}
return ti;
}
}

ColumnInfo包括一个静态方法,参数为POCO实体类的属性对象,从对象上获取自定义特性信息来初始化ColumnInfo实例

/// <summary>
/// POCO实体类属性对应的数据库列信息
/// </summary>
public class ColumnInfo
{
/// <summary>
/// 数据库列名称
/// </summary>
public string ColumnName { get; set; } /// <summary>
/// 是否结果值列,是的话,插入和更新操作不使用该属性
/// </summary>
public bool ResultColumn { get; set; } /// <summary>
/// 若对应的数据库类类型是DateTime,是否强制转换为UTC时间
/// </summary>
public bool ForceToUtc { get; set; } /// <summary>
/// 插入模板(暂未理解使用)
/// </summary>
public string InsertTemplate { get; set; } /// <summary>
/// 更新模板(暂未理解使用)
/// </summary>
public string UpdateTemplate { get; set; } /// <summary>
/// 从POCO实体类属性的特性初始化ColumnInfo
/// </summary>
public static ColumnInfo FromProperty(PropertyInfo propertyInfo)
{
// 获取属性所属的类实例上是否包括明确表示列信息的标志
var explicitColumns = propertyInfo.DeclaringType.GetCustomAttributes(typeof(ExplicitColumnsAttribute), true).Length > ; // Check for [Column]/[Ignore] Attributes
var colAttrs = propertyInfo.GetCustomAttributes(typeof(ColumnAttribute), true);
//属性明确指定列信息时,但是该属性没有列特性,返回null
if (explicitColumns)
{
if (colAttrs.Length == )
return null;
}
else
{
//没有明确指定时,该属性没有映射到数据库列,返回null
if (propertyInfo.GetCustomAttributes(typeof(IgnoreAttribute), true).Length != )
return null;
}
//类具有明确映射信息,则从列特性获取对应的数据信息或者没有明确信息时,则使用属性名称初始化。
var ci = new ColumnInfo();
// Read attribute
if (colAttrs.Length > )
{
var colattr = (ColumnAttribute) colAttrs[];
ci.InsertTemplate = colattr.InsertTemplate;
ci.UpdateTemplate = colattr.UpdateTemplate;
ci.ColumnName = colattr.Name == null ? propertyInfo.Name : colattr.Name;
ci.ForceToUtc = colattr.ForceToUtc;
if ((colattr as ResultColumnAttribute) != null)
ci.ResultColumn = true;
}
else
{
ci.ColumnName = propertyInfo.Name;
ci.ForceToUtc = false;
ci.ResultColumn = false;
}
return ci;
}
}
  PetaPoco中定义了一个缓存类,内部使用ReaderWriterLockSlim读写锁来控制读取和写入(ReaderWriterLockSlim支持多线程读取和单线程写入),
其公共方法Get的参数为缓存Key和创建函数,当缓存中没有对应的信息时,则使用创建函数创建信息并缓存起来。
方法内部先获取读取锁获取缓存信息,若没有则获取写入锁,获取后再次确认是否存在缓存信息,主要原因:获取写入锁需要释放之前所有的读写锁,防止在时间差创建了缓存信息。 
     /// <summary>
/// 缓存信息类
/// </summary>
internal class Cache<TKey, TValue>
{
/// <summary>
/// 读写锁
/// </summary>
private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); /// <summary>
/// 存储数据的字典
/// </summary>
private Dictionary<TKey, TValue> _map = new Dictionary<TKey, TValue>(); /// <summary>
/// 缓存数据的数目
/// </summary>
public int Count
{
get { return _map.Count; }
} /// <summary>
/// 根据Key获取对应的数据,若没有数据,则创建它并缓存起来
/// </summary>
public TValue Get(TKey key, Func<TValue> factory)
{
_lock.EnterReadLock();//设置读锁
TValue val;
try
{
if (_map.TryGetValue(key, out val))
return val;
}
finally
{
_lock.ExitReadLock();//释放读锁
}
_lock.EnterWriteLock();//没有找到,设置写锁
try
{
//再次检测,避免等待获取写锁的时间差中已创建信息
if (_map.TryGetValue(key, out val))
return val;
//使用传入的创建方法创建信息并缓存起来
val = factory();
_map.Add(key, val);
return val;
}
finally
{
_lock.ExitWriteLock();//释放写锁
}
} //清空缓存信息
public void Flush()
{
_lock.EnterWriteLock();
try
{
_map.Clear();
}
finally
{
_lock.ExitWriteLock();
}
}
}

PetaPoco源代码学习--2.TableInfo、ColumnInfo类和Cache类的更多相关文章

  1. PetaPoco源代码学习--0.目录贴

    2017年3季度后,以人力外包的形式派驻到甲方单位进行项目救急时,接触到了甲方单位的ASP.NET MVC项目的ORM框架,它以PetaPoco(2012年的老版本)进行改造升级的,当初就想学习一下这 ...

  2. PetaPoco源代码学习--3.Sql类

    PetaPoco对数据库的操作直接使用SQL语句,在代码中进行调用既可以直接传递SQL语句,也可以使用提供的SQL类来获取到SQL语句进行操作,直接传递SQL语句在内部实现中也是封装成Sql类传递到底 ...

  3. PetaPoco源代码学习--1.使用的Attribute介绍

    新版本的PetaPoco使用特性进行注解的形式来代替的老版本的映射类的形式.新版本中使用的特性主要包括以下几种: 名称   用途 TableNameAttribute Class 指定POCO实体类对 ...

  4. Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...

  5. struts2源代码学习之初始化(一)

    看struts2源代码已有一段时日,从今天開始,就做一个总结吧. 首先,先看看怎么调试struts2源代码吧,主要是下面步骤: 使用Myeclipse创建一个webproject 导入struts2须 ...

  6. 开源中国安卓client源代码学习(一) 渐变启动界面

    开源中国安卓client源代码学习(一) 渐变启动界面 准备学习安卓开发, 看到网上有人推荐开源中国安卓client的源代码, 说里面包括了大部分技术, 于是准备好好研究研究. 特开通此系列博客来记录 ...

  7. 读Flask源代码学习Python--config原理

    读Flask源代码学习Python--config原理 个人学习笔记,水平有限.如果理解错误的地方,请大家指出来,谢谢!第一次写文章,发现好累--!. 起因   莫名其妙在第一份工作中使用了从来没有接 ...

  8. nginx源代码学习资源(不断更新)

    nginx源代码学习是一个痛苦又快乐的过程,以下列出了一些nginx的学习资源. 首先要做的当然是下载一份nginx源代码,能够从nginx官方站点下载一份最新的. 看了nginx源代码,发现这是一份 ...

  9. djangorestframework-jwt自带的认证视图进行用户登录验证源代码学习

    Django REST framework JWT djangorestframework-jwt自带的认证视图进行用户登录验证源代码学习 SECRET_KEY = '1)q(f8jrz^edwtr2 ...

随机推荐

  1. Windows核心编程:第4章 进程

    Github https://github.com/gongluck/Windows-Core-Program.git //第4章 进程.cpp: 定义应用程序的入口点. // #include &q ...

  2. 03_python_基本数据类型

    一.基本数据类型 整数 bool 字符串: 可以保存少量数据并进行相应的操作 列表 list: 存大量数据 [] 元组 tuple: 不可改变的() 字典 dict: 保存键值对,一样可以存储大量的数 ...

  3. 跟着刚哥学习Spring框架--通过XML方式配置Bean(三)

    Spring配置Bean有两种形式(XML和注解) 今天我们学习通过XML方式配置Bean 1. Bean的配置方式 通过全类名(反射)的方式   √ id:标识容器中的bean.id唯一. √ cl ...

  4. C#6.0语言规范(九) 命名空间

    C#程序使用命名空间进行组织.命名空间既可以用作程序的“内部”组织系统,也可以用作“外部”组织系统 - 一种呈现暴露给其他程序的程序元素的方式. 提供了使用指令(使用指令)以便于使用命名空间. 编译单 ...

  5. webApp开发中的总结

    meta标签:  H5页面窗口自动调整到设备宽度,并禁止用户缩放页面 <meta name="viewport" content="width=device-wid ...

  6. odoo开发笔记 -- 模型一对多tree视图弹窗效果实现

    实现效果参考: 1. 开发者模式 -- 设置 -- 工作流 -- 编辑 -- 添加项目 2. 会计模块 -- 管理 -- 付款条款 -- 编辑/创建 实现方式,很简单.只要视图界面写个一对多关联字段就 ...

  7. mysql 常用操作命令

    mysql官网指南:http://dev.mysql.com/doc/refman/5.1/zh/sql-syntax.html 1.导出整个数据库mysqldump -u 用户名 -p --defa ...

  8. centos 7 安装 mysql 5.7

    1.环境 Centos 7 2.下载 官方网站https://dev.mysql.com/downloads/mysql/5.7.html#downloads ,选择要下载的版本,centos 7 同 ...

  9. Flexbox指南

    Flexbox布局(Flexible Box)模块旨在提供一个更加有效的方式制定.调整和分布一个容器里的项目布局,即使他们的大小是未知或者是动态的.(这里我们称为Flex). Flex布局主要思想是让 ...

  10. 全网最详细的Windows系统里Oracle 11g R2 Database服务器端(64bit)的下载与安装(图文详解)

    不多说,直接上干货! 环境: windows10系统(64位) 最好先安装jre或jdk(此软件用来打开oracle自带的可视化操作界面,不装也没关系:可以安装plsql,或者直接用命令行操作) Or ...