当把常用的特性填写到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. (leetcode162)find peak element

    1题目 A peak element is an element that is greater than its neighbors. Given an input array where num[ ...

  2. 【转】dlgdata.cpp line 40 断言失败

    原文网址:http://blog.csdn.net/onlyou930/article/details/6384075 在VS2010 运行一个C++ 程序,出现下图错误: 一看到这个,我头都大了.关 ...

  3. UWP 使用Windows Community Toolkit 的OneDrive service上传下载文件

    上一年年底写过两篇文章 UWP 使用OneDrive云存储2.x api(一)[全网首发] UWP 使用OneDrive云存储2.x api(二)[全网首发] 没想到半年之后,VS编译提示方法已经过时 ...

  4. hangfire的使用

    1.安装: hangfire包.StackExchange.Redis(abp下的hangfire则安装abp.hangfire) 2.配置 startup文件configuration方法添加以下代 ...

  5. Nmap命令的常用实例

    一.Nmap简介 nmap是一个网络连接端扫描软件,用来扫描网上电脑开放的网络连接端.确定哪些服务运行在哪些连接端,并且推断计算机运行哪个操作系统(这是亦称 fingerprinting).它是网络管 ...

  6. 11_python_闭包迭代器

    一.函数名(第一类对象) 函数名是一个变量,但它是一个特殊的变量,与括号配合可以执行函数的变量. def func(): print("呵呵") print(func) 结果: & ...

  7. 浏览器特权域XSS漏洞

    导语:科普什么是浏览器特权域XSS,可以用来干什么? 作者:天析 团队:Arctic Shell 为什么科普这个? 今天在群里看到有表姐说这个,然后恰好又有学姐在问什么是特权域XSS,于是就来说说这个 ...

  8. mysql 存储过程 游标嵌套

    基本表temp 包括 name, type, sendCity, getCity 分别对应物流送货司机名, 倒车的第几段, 发货城市, 收货城市 表结构 -- -------------------- ...

  9. D02-R语言基础学习

    R语言基础学习——D02 20190423内容纲要: 1.前言 2.向量操作 (1)常规操作 (2)不定长向量计算 (3)序列 (4)向量的删除与保留 3.列表详解 (1)列表的索引 (2)列表得元素 ...

  10. WIN10安装scrapy/channels等不成功的解决方式

    问题 在Win10机器上,不管是安装scrapy还是channels,都需要安装一个包,叫做twisted.正是这个twisted,导致出现一系列的奇葩错误,让我一度以为我的Pycharm坏了,还改了 ...