博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【手撸一个ORM】第二步、封装实体描述和实体属性描述
阅读量:5132 次
发布时间:2019-06-13

本文共 6574 字,大约阅读时间需要 21 分钟。

一、实体属性描述 [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
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 > 0) { var tableName = ((MyTableAttribute)tableAttr[0]).TableName; TableName = string.IsNullOrWhiteSpace(tableName) ? type.Name.Replace("Entity", "") : tableName; } else { TableName = Name; } Properties = new List
(); 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
Dict = new ConcurrentDictionary
(); 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; } } }}

 

转载于:https://www.cnblogs.com/diwu0510/p/10663339.html

你可能感兴趣的文章
初学XPath,其实很简单
查看>>
(一)Redis初学教程之安装篇
查看>>
JAVA作业-简易计算器
查看>>
继续前进
查看>>
SharePoint2010 对象模型 关联列表
查看>>
python下的selenium和PhantomJS
查看>>
分享一个IIS日志分析工具-LogParse
查看>>
Ignatius and the Princess IV (水题)
查看>>
C#导入导出Excele数据
查看>>
html table导出到Excel中,走后台保存文件,js并调用另保存
查看>>
ccf模板生成
查看>>
Exadata V2 Battery Replacement
查看>>
Oracle数据库案例整理-Oracle系统执行时故障-内存过少导致分配共享内存失败
查看>>
Android Gradle Task-中文
查看>>
hiho一下第91周《Events Arrangement》(前半部分)
查看>>
Activity返回值[转]
查看>>
1_dbworld
查看>>
"%Error opening tftp://255.255.255.255/network config"
查看>>
HDU 1022 Train Problem I stack 基础题
查看>>
StringUtils.htmlEncode()--html标签过滤方法实现
查看>>