当把常用的特性填写到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. RGB-D 室内导航 paper

    摘要: 最近打算使用Kinect实现机器人的室内导航,收集了近年来的一些比较好的文章.<基于Kinect系统的场景建模与机器人自主导航>.<Mobile Robots Navigat ...

  2. C#操作数据表中XML格式的数据

    以前还真没有见过数据表中存储XML格式的数据,刚开始听说的时候,还以为是数据表中有XML的字段类型, 再了解,其实也就是字符串类型的,只不过字符串的格式是XML格式的.确实孤陋寡闻!汗... (可添加 ...

  3. AngularJS指令封装高德地图组件

    1 概述 公司移动门户原来是基于AngularJS指令封装的百度地图组件,用于签到.签退.定位等功能,在使用过程中发现百度地图频繁的弹出广告,所以打算重新引用其它地图组件,最后决定基于AngularJ ...

  4. 关于GROUP BY和聚合函数

    可以这样去理解group by和聚合函数 转自 http://www.cnblogs.com/wiseblog/articles/4475936.html 写在前面的话:用了好久group by,今天 ...

  5. 《Python自动化运维之路》 业务服务监控(二)

    文件内容差异对比方法 使用diffie模块实现文件内容差异对比.dmib作为 Python的标准库模块,无需安装,作用是对比文本之间的差异,且支持输出可读性比较强的HTML文档,与 Linux下的di ...

  6. XSS钓鱼某网约车后台一探究竟,乘客隐私暴露引发思考

    i春秋作家:onls辜釉 最近的某顺风车命案,把网约车平台推上了风口浪尖,也将隐私信息管理.审查的讨论面进一步扩大.这让我不禁联想起自己今年春节的遭遇,当时公司放假准备回家过年,我妈给我推荐了一个在我 ...

  7. python线程死锁与递归锁

    死锁现象 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去. 此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待 ...

  8. python连接mysql数据库简单例子

    今天用pyhton2连接本地的mysql数据库,总的来说比较简单,但还是遇到一些小问题 代码如下: # -*- coding: utf-8 -*- import os import MySQLdb i ...

  9. [原创]K8_C段旁注工具6.0 新增SMB漏洞扫描

    工具: K8_C段旁注工具6.0_0510[K.8]编译: 自己查壳组织: K8搞基大队[K8team]作者: K8拉登哥哥博客: http://qqhack8.blog.163.com发布: 201 ...

  10. 基于sql service会话共享,实现SSO

    1:session的存储基于sql service数据库来存储 2:修改sql service中会话管理的系统存储过程 3:实现几个站点的会话共享 4:应用共享会话,实现单点登录