一、实体属性描述 [MyProperty.cs]

  • Name,属性名称
  • PropertyInfo,反射获取的属性信息,后面很多地方需要通过该属性获取对应的实体类型,或调用SetValue进行赋值
  • FieldName,对应的数据表列名
  • IsKey,是否主键
  • IsMap,查询时是否映射该属性,若属性非值类型或string,则默认为false,其他默认为true;若需手动设置为false,如计算属性,需要在MyColumnAttribute中配置 IsMap=false
  • InsertIgnore,插入时忽略
  • UpdateIgnore,更新时忽略
  • JoinAble,是否可以通过Join进行查询,等同于导航属性
  • ForignKey,如果可以通过Join查询,对应的外键名
  • MasterKey,如果可以通过Join查询,对应的主表Id,默认为Id,若主表主键列名不是Id,需手动在MyForeignKey中配置 MasterKey="StudentId"
using System.Reflection;

namespace MyOrm.Reflections
{
public class MyProperty
{
public string Name { get; set; } public PropertyInfo PropertyInfo { get; set; }public string FieldName { get; set; } public bool IsKey { get; set; } public bool IsMap { get; set; } = true; public bool InsertIgnore { get; set; } public bool UpdateIgnore { get; set; } public bool JoinAble { get; set; } public string ForeignKey { get; set; } public string MasterKey { get; set; } public MyProperty(PropertyInfo property)
{
Name = property.Name;
TypeName = property.PropertyType.Name;
PropertyInfo = property; if (property.IsMapAble())
{
// 判断是否主键
var keyAttribute = property.GetKeyAttribute();
if (keyAttribute != null)
{
// 有
IsKey = true;
FieldName = string.IsNullOrWhiteSpace(keyAttribute.FieldName) ? Name : keyAttribute.FieldName;
if (keyAttribute.IsIncrement)
{
// 如果是自增列,不能插入和修改
InsertIgnore = true;
UpdateIgnore = true;
}
else
{
// 如果不是自增列,可插入但不能修改
InsertIgnore = true;
}
}
else if (Name == "Id")
{
FieldName = "Id";
IsKey = true;
InsertIgnore = true;
UpdateIgnore = true;
}
else
{
// 可映射的属性
var columnAttribute = property.GetMyColumnAttribute(); if (columnAttribute != null)
{
FieldName = string.IsNullOrWhiteSpace(columnAttribute.ColumnName)
? Name
: columnAttribute.ColumnName;
InsertIgnore = columnAttribute.Ignore || columnAttribute.InsertIgnore;
UpdateIgnore = columnAttribute.Ignore || columnAttribute.UpdateIgnore;
}
else
{
FieldName = Name;
}
}
}
else if (property.IsJoinAble())
{
// 可关联查询的属性
IsMap = false;
JoinAble = true;
UpdateIgnore = true;
InsertIgnore = true;
var foreignAttribute = property.GetForeignKeyAttribute();
if (foreignAttribute == null)
{
ForeignKey = Name + "Id";
MasterKey = "Id";
}
else
{
ForeignKey = string.IsNullOrWhiteSpace(foreignAttribute.ForeignKey)
? Name + "Id"
: foreignAttribute.ForeignKey;
MasterKey = string.IsNullOrWhiteSpace(foreignAttribute.MasterKey)
? "Id"
: foreignAttribute.MasterKey;
}
}
else
{
// 其他属性
IsMap = false;
UpdateIgnore = true;
InsertIgnore = true;
}
}
}
}

二、数据实体描述 [MyEntity.cs]

  • KeyColumn,数据表中主键列名称
  • Name,实体名称
  • TableName,实体对应的数据表名称
  • IsSoftDelete,是否软删除(继承ISoftDelete),后面会有说明
  • IsCreateAudit,是否创建审计(保存创建人、创建时间)
  • IsUpdateAudit,是否更新审计(保存修改人、修改时间)
  • Properties,封装过的属性信息列表-考虑过这里用字典保存,但是因为后面需要大量的遍历操作,个人感觉还是List用起来方便,所以最终选择了List类型
using MyOrm.Attributes;
using MyOrm.Commons;
using System;
using System.Collections.Generic; namespace MyOrm.Reflections
{
public class MyEntity
{
public string KeyColumn { get; set; } public string Name { get; set; } public string TableName { get; set; } public bool IsSoftDelete { get; set; } public bool IsCreateAudit { get; set; } public bool IsUpdateAudit { get; set; } public List<MyProperty> Properties { get; set; } public MyEntity(Type type)
{
Name = type.Name;
IsSoftDelete = type.IsInstanceOfType(typeof(ISoftDelete));
IsCreateAudit = type.IsInstanceOfType(typeof(ICreateAudit));
IsUpdateAudit = type.IsInstanceOfType(typeof(IUpdateAudit)); var tableAttr = type.GetCustomAttributes(typeof(MyTableAttribute), false);
if (tableAttr.Length > )
{
var tableName = ((MyTableAttribute)tableAttr[]).TableName;
TableName = string.IsNullOrWhiteSpace(tableName) ? type.Name.Replace("Entity", "") : tableName;
}
else
{
TableName = Name;
} Properties = new List<MyProperty>(); foreach (var propertyInfo in type.GetProperties())
{
var property = new MyProperty(propertyInfo);
if (property.IsKey)
{
KeyColumn = property.FieldName;
}
Properties.Add(property);
}
}
}
}

三、实体容器

上面对实体及其属性进行了封装,但是如果每次都需要反射获取,那性能损耗会非常厉害,因此将生成的内容缓存在起来便十分必要了。这里使用的是线程安全的静态字典作为缓存容器。

using System;
using System.Collections.Concurrent; namespace MyOrm.Reflections
{
public class MyEntityContainer
{
private static readonly ConcurrentDictionary<string, MyEntity> Dict =
new ConcurrentDictionary<string, MyEntity>(); public static MyEntity Get(Type type)
{
if (type == null) throw new ArgumentNullException(nameof(type));
if (Dict.TryGetValue(type.FullName ?? throw new InvalidOperationException(), out var result))
{
return result;
}
else
{
var entity = new MyEntity(type);
Dict.TryAdd(type.FullName, entity);
return entity;
}
}
}
}

最新文章

  1. ABP文档 :Overall - Introduction
  2. SQLite常用语句
  3. JQuery EasyUI window 用法
  4. MSSQL 判断临时表是否存在
  5. ASP.NET MVC中的拦截器
  6. 《Head First 设计模式》ch.2 观察者(Observer)模式
  7. 【鸡渣饲料系列】《Introdution to 3D Game Programming With DirectX11》 代码转移至vs2015
  8. Eclipse里面开发ExtJS程序
  9. 18. 4Sum
  10. Jasper_crosstab_display a value of field in crosstab total row
  11. SQL数据库插入文本信息
  12. Oracle Hint用法总结
  13. ExtJS拖拽效果
  14. 2014年度辛星完全解读html部分
  15. LevelDB的源码阅读(三) Put操作
  16. anguar-select2
  17. 《前端之路》之 JavaScript 进阶技巧之高阶函数(下)
  18. HTML5 canvas clearRect() 方法
  19. java当中的强引用,软引用,弱引用,虚引用
  20. iOS 运行时使用(交换两个方法)

热门文章

  1. Redis常用数据结构和操作
  2. CentOS7 默认防火墙firewalld
  3. find命令的基础用法以及按文件修改时间查找文件
  4. cookie的保存与提取
  5. 使用svg的几种方式
  6. 【LeetCode】063. Unique Paths II
  7. sublime插件insertDate显示ISO时间
  8. AtCoder Regular Contest 073 E:Ball Coloring
  9. linux 命令2
  10. JVM StackOverflowError vs. OutOfMemoryError