PetaPoco源代码学习--2.TableInfo、ColumnInfo类和Cache类
当把常用的特性填写到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类的更多相关文章
- PetaPoco源代码学习--0.目录贴
2017年3季度后,以人力外包的形式派驻到甲方单位进行项目救急时,接触到了甲方单位的ASP.NET MVC项目的ORM框架,它以PetaPoco(2012年的老版本)进行改造升级的,当初就想学习一下这 ...
- PetaPoco源代码学习--3.Sql类
PetaPoco对数据库的操作直接使用SQL语句,在代码中进行调用既可以直接传递SQL语句,也可以使用提供的SQL类来获取到SQL语句进行操作,直接传递SQL语句在内部实现中也是封装成Sql类传递到底 ...
- PetaPoco源代码学习--1.使用的Attribute介绍
新版本的PetaPoco使用特性进行注解的形式来代替的老版本的映射类的形式.新版本中使用的特性主要包括以下几种: 名称 用途 TableNameAttribute Class 指定POCO实体类对 ...
- Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...
- struts2源代码学习之初始化(一)
看struts2源代码已有一段时日,从今天開始,就做一个总结吧. 首先,先看看怎么调试struts2源代码吧,主要是下面步骤: 使用Myeclipse创建一个webproject 导入struts2须 ...
- 开源中国安卓client源代码学习(一) 渐变启动界面
开源中国安卓client源代码学习(一) 渐变启动界面 准备学习安卓开发, 看到网上有人推荐开源中国安卓client的源代码, 说里面包括了大部分技术, 于是准备好好研究研究. 特开通此系列博客来记录 ...
- 读Flask源代码学习Python--config原理
读Flask源代码学习Python--config原理 个人学习笔记,水平有限.如果理解错误的地方,请大家指出来,谢谢!第一次写文章,发现好累--!. 起因 莫名其妙在第一份工作中使用了从来没有接 ...
- nginx源代码学习资源(不断更新)
nginx源代码学习是一个痛苦又快乐的过程,以下列出了一些nginx的学习资源. 首先要做的当然是下载一份nginx源代码,能够从nginx官方站点下载一份最新的. 看了nginx源代码,发现这是一份 ...
- djangorestframework-jwt自带的认证视图进行用户登录验证源代码学习
Django REST framework JWT djangorestframework-jwt自带的认证视图进行用户登录验证源代码学习 SECRET_KEY = '1)q(f8jrz^edwtr2 ...
随机推荐
- [C# 面试总结]9个点如何画10条线
问题描述 9个点画10条直线,要求每条直线上至少3个点,相信这道理题目很多朋友在面试的时候都遇到过的(同时自己在面试的时候也遇到过),所以这里记录下来以备复习. 解决方法1:
- Git之初识
我的Github地址:https://github.com/shinianzongjishinianxin 初见总是美好的,可是我第一次看到github有点纠结,因为看不懂,然而最终半蒙半猜还是注册完 ...
- MVC中通过ajax判断输入的内容是否重复(新手笔记,请各位多多指教)
控制器代码: public string ValidateCarID(string carid)//这里接收ajax传递过来的值 { string result; Car car = db.Car.F ...
- UWP 大爆炸你个锤子
今天看到 叫我蓝火火 s的 UWP中实现大爆炸效果(一) ,我也来说一下我的app [小薇自然语言处理]实现的大爆炸技术. 看一下效果先. 我的控件是基于wrappanel的,正如蓝火火说的,这样看 ...
- ionic 2.x 3.x项目结构解析
myApp │ config.xml //项目配置文件,包名.名称.minSdkVersion等都在此处配置 │ ionic.config.json │ package.json //项目依赖文件列表 ...
- 配置kali linux
在7月底的时候,安全加介绍Fireeye出品的 免费恶意软件分析工具FlareVM,还可进行逆向工程和渗透测试 .今天是看到绿盟科技的一篇介绍Kali Linux配置的文章,这个工具也进入了 渗透测试 ...
- Django(ORM查询2)
day70 ORM训练专题 :http://www.cnblogs.com/liwenzhou/articles/8337352.html 内容回顾 1. ORM 1. ORM ...
- C#6.0语言规范(八) 语句
C#提供了各种语句.大多数这些语句对于使用C和C ++编程的开发人员来说都很熟悉. statement : labeled_statement | declaration_statement | em ...
- linux系统坏了,进不了登陆界面怎么办?
装oracle时,命令弄错了,结果系统崩溃之后就进不去系统了,启动后光标一直在闪烁,就是不显示登陆界面. 网上查了很多,什么grub引导之类的,完全没办法恢复系统. 系统坏了倒是无所谓,主要是系统上还 ...
- vue教程3-05 vue组件数据传递、父子组件数据获取,slot,router路由
vue教程3-05 vue组件数据传递 一.vue默认情况下,子组件也没法访问父组件数据 <!DOCTYPE html> <html lang="en"> ...