当把常用的特性填写到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. 使用HAProxy实现sql server读库的负载均衡

    前置条件 使用sqlserver的发布订阅功能实现读写分离,并创建多个读库. 本文的负载均衡是针对多个读库而言的. 测试环境 vmware 10 64位 windows server 2008 R2 ...

  2. Visual Studio Code 显示隐藏的.git文件和目录

    在默认设置中,Visual Studio Code 将下列文件文件排除在显示列表中: "files.exclude": { "**/.git": true, & ...

  3. winform 查找控件并获取特定类型控件

    //通过反射获取所有控件集合 System.Reflection.FieldInfo[] fieldInfo = this.GetType().GetFields(System.Reflection. ...

  4. 剑指offer编程题Java实现——面试题3二维数组中的查找

    题目描述 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数.   下面是我实现的代码 ...

  5. 【转】 js数组 Array 交集 并集 差集 去重

    原文:http://blog.csdn.net/ma_jiang/article/details/52672762 最劲项目需要用到js数组去重和交集的一些运算,我的数组元素个数可能到达1000以上, ...

  6. 关于IE9 table显示错位的问题

    首先,win10无法安装IE9,所以需要用IE11模拟IE9,这样:http://www.w10zj.com/Win10xy/Win10yh_638.html: 其次,table显示错位的可能原因:h ...

  7. 尝试利用slmail的漏洞来getshell

    作者:Joe   本文属于Arctic shell原创内容计划文章,转载请注明原文地址! 二进制,计算机才可以理解的低级语言,简单来说它是一种信号,用电信号为例,0就是断电,而1就是有电,这样子010 ...

  8. 用代码来细说Csrf漏洞危害以及防御

    开头: 废话不多说,直接进主题. 0x01 CSRF介绍:CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session ...

  9. java变量初始化顺序

    第一次实例化一个类时,初始化优先顺序为: 1.父类中的静态成员变量和静态代码块初始化 2.本类中的静态成员变量和静态代码块初始化 3.父类中的实例成员初始化 4.父类中的构造方法 5.本类中的实例成员 ...

  10. 转---30 分钟学会 Flex 布局

    正文从这开始- Flex 基本概念: 在 flex 容器中默认存在两条轴,水平主轴(main axis) 和垂直的交叉轴(cross axis),这是默认的设置,当然你可以通过修改使垂直方向变为主轴, ...