减少重复工作,通过泛型、反射写一个通用的Ado.net操作数据库的简单orm底层

创建一个基类BaseEntity:

 public class BaseEntity
    {
        [PrimaryKey]
        public int Id { get; set; }
        public DateTime CreateTime { get; set; }
        public Status Status { get; set; }
        public string Remark { get; set; }
    }

    /// <summary>
    /// 自增主键标识
    /// </summary>
    public class PrimaryKey : Attribute
    {

    }

  然后创建一个泛型底层类,这里用的数据库是mysql,如果是其它数据库,需要注意相应的关键字,比如sqlserver中user表在写sql时需要写成“[user]”。

/// <summary>
    /// 已实现增删改查的底层基类 T类的属性需要和表字段保持一致
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BaseAccessory<T> where T : BaseEntity, new()
    {
        protected DBHelper dBHelper = new DBHelper();
        private Type Type;
        private PropertyInfo[] Props;
        private PropertyInfo KeyProp;//主键属性

        /// <summary>
        /// 构造函数
        /// </summary>
        public BaseAccessory()
        {
            Type = typeof(T);
            //下一步 将类型对应的属性写入缓存
            Props = Type.GetProperties();
            KeyProp = Props.First(f => f.CustomAttributes.Count(d => d.AttributeType == typeof(PrimaryKey)) > 0);
        }

        /// <summary>
        /// 根据主键获取实体数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public T GetModel(int keyValue)
        {
            var sql = $"select {string.Join(",", Props.Select(f => f.Name))} from {Type.Name} where {KeyProp.Name} = {keyValue}";
            var cmd = dBHelper.GetSqlStringCommond(sql);
            using (var reader = dBHelper.ExecuteReader(cmd))
            {
                while (reader.Read())
                {
                    var t = new T();
                    foreach (var prop in Props)
                    {
                        prop.SetValue(t, reader[prop.Name]);
                    }
                    return t;
                }
            }
            return null;
        }

        /// <summary>
        /// 更新实体
        /// </summary>
        /// <param name="model"></param>
        /// <returns>受影响的行数</returns>
        public int Update(T model, Trans t = null)
        {
            var sql = $"UPDATE {Type.Name} SET {string.Join(",", Props.Select(f => f.Name + "=‘" + f.GetObjValue(model) + "‘"))} where {KeyProp.Name}={KeyProp.GetValue(model)} ";
            var cmd = dBHelper.GetSqlStringCommond(sql);
            if (t is null) { return dBHelper.ExecuteNonQuery(cmd); }
            else { return dBHelper.ExecuteNonQuery(cmd, t); }
        }

        /// <summary>
        /// 写入实体
        /// </summary>
        /// <param name="model"></param>
        /// <returns>受影响的行数</returns>
        public int Insert(T model, Trans t = null)
        {
            var sql = [email protected]"INSERT INTO {Type.Name} ({string.Join(",", Props.Where(f => f.Name != KeyProp.Name).Select(f => f.Name))}) VALUES({string.Join(",", Props.Where(f => f.Name != KeyProp.Name).Select(f => "‘" + f.GetObjValue(model) + "‘"))}); select @@IDENTITY";
            var cmd = dBHelper.GetSqlStringCommond(sql);
            object id;
            if (t is null) { id = dBHelper.ExecuteScalar(cmd); }
            else { id = dBHelper.ExecuteScalar(cmd, t); }
            return Convert.ToInt32(id);
        }

        public int Delete(int keyValue, Trans t = null)
        {
            var sql = $"delete  {Type.Name} where {KeyProp.Name} = {keyValue}";
            var cmd = dBHelper.GetSqlStringCommond(sql);
            if (t is null) { return dBHelper.ExecuteNonQuery(cmd); }
            else { return dBHelper.ExecuteNonQuery(cmd, t); }
        }

    }

  最后在业务代码中就可以调用该类:

 /// <summary>
    /// 用户表实体类 属性需要和表字段保持一致
    /// </summary>
    public class User : BaseEntity
    {
        public string LoginName { get; set; }
        public string Password { get; set; }
        public string RealName { get; set; }
        public string PhoneNumber { get; set; }
    }

public class UserAccessory : BaseAccessory<User>
    {

    }

public class Main{
        public void TestMethod1()
        {
            UserAccessory userDal = new UserAccessory();
            var user = userDal.GetModel(2);
            user.LoginName = "哈哈泛型的强大,更新成功";
            userDal.Update(user);
            user.LoginName = "哈哈泛型的强大,写入成功";
            var id = userDal.Insert(user);
        }
}

  

原文地址:https://www.cnblogs.com/hepeng/p/8711054.html

时间: 2024-09-29 18:28:09

减少重复工作,通过泛型、反射写一个通用的Ado.net操作数据库的简单orm底层的相关文章

《用Java写一个通用的服务器程序》01 综述

最近一两年用C++写了好几个基于TCP通信类型程序,都是写一个小型的服务器,监听请求,解析自定义的协议,处理请求,返回结果.每次写新程序时都把老代码拿来,修改一下协议解析部分和业务处理部分,然后就一个新的程序就诞生了.如此这般做了几回,就萌生了一个想法:是不是可以做一个通用的服务器程序,每次只要实现很少的代码就可以构建的一个新的服务器程序? 巧的是在用C++写代码的时候,我刚好碰到过一个叫做Push Framework的开源项目(在这里可以找到:www.pushframework.com),就是

Hello Python!用python写一个抓取CSDN博客文章的简单爬虫

网络上一提到python,总会有一些不知道是黑还是粉的人大喊着:python是世界上最好的语言.最近利用业余时间体验了下python语言,并写了个爬虫爬取我csdn上关注的几个大神的博客,然后利用leancloud一站式后端云服务器存储数据,再写了一个android app展示数据,也算小试了一下这门语言,给我的感觉就是,像python这类弱类型的动态语言相比于java来说,开发者不需要分太多心去考虑编程问题,能够把精力集中于业务上,思考逻辑的实现.下面分享一下我此次写爬虫的一下小经验,抛砖引玉

《用Java写一个通用的服务器程序》02 监听器

在一个服务器程序中,监听器的作用类似于公司前台,起引导作用,因此监听器花在每个新连接上的时间应该尽可能短,这样才能保证最快响应. 回到编程本身来说: 1. 监听器最好由单独的线程运行 2. 监听器在接到新的连接之后,处理连接的方法需要尽快返回 在Java Push Framework中,因为需要同时监听普通客户端和服务器监视服务的客户端,所以定义两种监听器:Acceptor和MonitorAcceptor. 由于两者的关于监听部分的逻辑是相同的,因此首先定义了抽象类Listener来实现了监视器

《用Java写一个通用的服务器程序》03 处理新socket

在讲监听器时说过处理的新的socket要尽快返回,监听器调用的是ClientFactory的createPhysicalConnection方法,那么就来看这个方法: public boolean createPhysicalConnection(PushClientSocket socket, boolean isObserver, ListenerOptions listenerOptions) { PhysicalConnectionPool thePhysicalConnectionPo

手把手教你写一个通用的helm chart

[TOC] 1. 模板介绍 首先,放上此模板链接: https://github.com/ygqygq2/charts/tree/master/mod-chart 此chart可当作POD单image的通用模板,只需要使用sed替换下chart名,并修改下README.md和NOTES.txt就可以了.下文,我通过复制此chart成example-chart来作示范说明. [[email protected] mod-chart]# tree . ├── Chart.yaml ├── READM

【转】写一个通用的事件侦听器函数

// event(事件)工具集,来源:github.com/markyun markyun.Event = { // 页面加载完成后 readyEvent : function(fn) { if (fn==null) { fn=document; } var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = fn; } else { window.onload = functi

写一个通用的事件侦听器函数

/ event(事件)工具集 markyun.Event = { // 页面加载完成后 readyEvent : function(fn) { if (fn==null) { fn=document; } var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = fn; } else { window.onload = function() { oldonload(); fn(

WangSql -- SqlExe 一个操作数据库的简单框架

这只是开篇,会持续更新. 目前用到反射较多,影响性能啊,后期考虑用映射,不过映射恐怕又要写配置文件,麻烦啊. 1.项目结构 目前支持 SqlServer Access Oracle MySql 要支持其他数据库可以自己添加. 2.功能详解 2.1 database.config 将database.config放到网站根目录,名字不可改. <?xml version="1.0" encoding="utf-8" ?> <configuration&

写一个框架的详细步骤

定位 所谓定位就是回答几个问题,我出于什么目的要写一个框架,我的这个框架是干什么的,有什么特性适用于什么场景,我的这个框架的用户对象是谁,他们会怎么使用,框架由谁维护将来怎么发展等等. 如果你打算写框架,那么肯定心里已经有一个初步的定位,比如它是一个缓存框架.Web MVC框架.IOC框架.ORM/数据访问框架.RPC框架或是一个用于Web开发的全栈式框架. 是 否要重复造轮子?除非是练手项目,一般我们是有了解决不了问题的时候才会考虑不使用既有的成熟的框架而重复造轮子的,这个时候需要列出新框架主