ORM框架学习(二)

ORM框架--新增数据

今天的内容对照上一节内容,上一节内容是对数据的查询,本节主要是对数据的新增。程序入口代码如下

static void Main(string[] args)
        {
            SqlHelper help = new SqlHelper();
            UserModel u1 = help.Query<UserModel>(1);
            Company com1 = help.Query<Company>(2);
            bool re1 = help.AddData(u1);
            bool re2 = help.AddData(com1);
        }

AddData()方法和Query()方法一样。都是限制为where T:BaseModel的泛型方法。AddData代码如下所示

 public bool AddData<T>(T t) where T:BaseModel
        {
            bool re = true;

            try
            {
                Type type=typeof(T);
                string conStr = "Server=127.0.0.1;Database=master; integrated security=SSPI";
                string AddStr = SqlBuilder<T>.GetSql(SqlBuilder<T>.SqlType.AddSql);
                var sqlpara = type.GetProperties().FilterKey().Select(p => new SqlParameter("@" + p.GetMappingName(), p.GetValue(t) ?? DBNull.Value)).ToArray();
                using (SqlConnection conn = new SqlConnection(conStr))
                {
                    SqlCommand cmd = new SqlCommand(AddStr, conn);
                    cmd.Parameters.AddRange(sqlpara);
                    conn.Open();
                    int result= cmd.ExecuteNonQuery();
                    return result > 0;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
                re = false;
            }
            return re;
        }

1.按照特性过滤不需要实体字段

因为我们现在做的是新增,数据库设计id为自增类型,所以在insert时,我们不需要新增id字段,所以就要想办法把id字段过滤。解决的办法是通过给ID设置特性ThemeKeyAttribute,特性定义如下所示

/// <summary>
    /// 主键特性
    /// </summary>
    public class ThemeKeyAttribute:Attribute
    {
    
    }

在特性方法里面没有任何实现,主要目的是用来做标记。同时,我们需要为id字段添加上面定义的特性,如下所示

public class BaseModel
    {
        [ThemeKeyAttribute]
        public int Id { get; set; }
    }

这样一来,就把company实体和User尸体的ID字段加上了特性。我们需要在获取实体属性时,调用过滤主键方法

Filter是一个IEnumerable类型那个的扩展方法,定义如下所示:

public static IEnumerable<PropertyInfo> FilterKey(this IEnumerable<PropertyInfo> props)
        {
            return props.Where(p=>!p.IsDefined(typeof(ThemeKeyAttribute),true));
        }

在Filter方法中,直接传入当前的属性集合类型,把标记有ThemeKeyAttribute的属性过滤掉后再返回集合。

在Filter方法中,我们通过方法p.IsDefined(typeof(ThemeKeyAttribute),true)就可以判断一个类型是否具有某种特性。

2.泛型缓存

由于在执行AddData()方法时,我们的sql语句结构都是类似的(insert into [tab]([]) values(‘‘)),为了提高代码执行效率,避免每次执行AddData()方法都去初始化一次sql语句,我们决定采用泛型缓存的方法,定义如下一个泛型类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Theme.Model;
using Theme.Framework;
namespace Theme.DAL
{
    public  class SqlBuilder<T> where T:BaseModel
    {
        private static string FindSql=null;
        private static string AddSql=null;
        static SqlBuilder()
        {
            {
                Type t = typeof(T);
                string table = t.GetMappingName();
                string props = string.Join(",", t.GetProperties().Select(p => "[" + p.GetMappingName() + "]"));
                T ti = Activator.CreateInstance<T>();
                FindSql = string.Format("select {0} from [{1}] where [email protected] ", props, table);
            }
            {
                Type type = typeof(T);
                string table = type.GetMappingName();
                string param = string.Join(",", type.GetProperties().FilterKey().Select(p => "[" + p.GetMappingName() + "]"));
                string valueStr = string.Join(",", type.GetProperties().FilterKey().Select(p => "@" + p.GetMappingName()));

                //id为自增的关键字,不能插入,应该把ID屏蔽
                AddSql = string.Format("insert into [{0}]({1}) values({2})", table, param, valueStr);
            }
        }
        public static string GetSql(SqlType sqltype)
        {
            switch (sqltype)
            {
                case SqlType.AddSql:
                    return AddSql;
                case SqlType.FindSql:
                    return FindSql;
                default:
                    throw new Exception("wrong sqlType");
            }
        }
        public enum SqlType
        {
            FindSql,
            AddSql
        }
    }
}

注意,要通过限制当前类只能是继承了BaseModel父类的才能访问。我们把sql语句定义成静态字段,在每次使用该类之前,该类进行初始化生成FindSql和AddSql语句。这样确保了一个类型的对象只会初始化一次sql语句,这样就节省了多对象调用反复拼装sql语句的问题。

3.参数化sql,避免sql注入

为了避免SQL注入问题的发生,我们通过参数化的方法拼装SQL执行语句,如下图所示:

在具体执行sql语句时,添加一下各个参数的值,如下图所示:

原文地址:https://www.cnblogs.com/zxwDont/p/11473874.html

时间: 2024-10-28 23:14:23

ORM框架学习(二)的相关文章

Struts2框架学习(二) Action

Struts2框架学习(二) Action Struts2框架中的Action类是一个单独的javabean对象.不像Struts1中还要去继承HttpServlet,耦合度减小了. 1,流程 拦截器拦截请求,创建代理Action对象,执行方法,返回结果,界面跳转. 拦截器解析请求路径,获取Action的名称,到配置文件中查找action的完整类名,利用反射创建对象. 每请求一次,就创建一个对象,所以action是多例的,也是线程安全的. 2,关系 请求的路径和配置文件的对应关系: 配置文件中包

Android Afinal框架学习(二) FinalActivity 一个IOC框架

框架地址:https://github.com/yangfuhai/afinal 对应的源码: net.tsz.afinal.annotation.view.* FinalActivity FinalActivity是一个基础类,结合注解实现了,依赖注入(view的资源id,常用的监听器), 利用set方式注入 完全注解方式就可以进行UI绑定和事件绑定,无需findViewById和set event Listener 这个过程:initInjectedView>findViewById.set

打造android ORM框架opendroid(二)——自动创建数据库

在上一篇博客<打造android ORM框架opendroid(一)--ORM框架的使用>中相信你已经了解了opendroid的使用,那么从这篇博客开始,我们正式进入opendroid的源码分析,打造一款自己的ORM框架! 在正式开始之前,你需要保证手里有一份opendroid的源码,如果还没下载opendroid,请到http://git.oschina.net/qibin/OpenDroid 下载opendroid的源码. 任何数据库操作都是从创建数据库开始的,今天我们就来看看opendr

Hibernate框架学习(二)——api详解

一.Configuration对象 功能:配置加载类,用于加载主配置,orm元数据加载. 1 //1.创建,调用空参构造(还没有读配置文件) 2 Configuration conf=new Configuration(); 3 //2.读取指令配置文件=>空参加载方法,加载src下的hibernate.cfg.xml文件 4 conf.configure(); 5 6 //3.读取指定orm元数据(扩展),如果主配置中已经引入映射配置,不需要手动加载 7 //conf.addResource(

Android 学习笔记之AndBase框架学习(二) 使用封装好的进度框,Toast框,弹出框,确认框...

PS:渐渐明白,在实验室呆三年都不如在企业呆一年... 学习内容: 1.使用AbActivity内部封装的方法实现进度框,Toast框,弹出框,确认框...   AndBase中AbActivity封装好了许多方法提供我们去使用,使得在使用的时候更加的方便,只需要传递相关参数即可..省去了我们自己使用基础的函数进行构造...   就好比进度框,Toast框,弹出框,确认框...这些基本的东西都在AndBase的AbActivity封装好了...我们只需要传递参数调用其中内部的方法就可以完成这些视

laravel框架学习(二)

在了解Laravel框架的基本结构之后,初步认识访问过程中路由的使用方法,以一套基本的学生信息增删改查来迅速学习框架开发. 首先了解几个目录文件作为开发的主要阵地: 1. /app/Http/routes.php 路由文件,一切访问从路由开始 2./app/Http/Controllers 控制器目录,我们写的控制器都放在该目录下 3./app/config Laravel配置文件夹一般修改.env文件 4./.env 经常修改配置的文件,数据库配置就在这里 5./public Laravel框

ORM框架学习之EF

首先推荐一篇很好的EF文章翻译,可以系统的学习一遍. <Entity Framework 6 Recipes>中文翻译系列 EF使用体会 优点: 可以省去Ado.net复杂的管道连接代码. 通过简单的引用就能完成对数据库的连接和开发. 可以省去一些SQL语句的编写,对一些底层可能需要适配多数据库提供了一些方便. 缺点: 学习成本较高,如果不怎么懂SQL,索引的一些数据库知识,也写不太好相对优化的Linq查询,所有EF既要懂Sql又懂Linq是最好的. 比较大,EF的dll默认是连接SqlSer

TP框架学习(二)

简单的增删改查 1 1.创建一个index.php文件 2 定义应用App目录名 3 导入窗口入口文件 4 开启调试模式//出现错误会报告出错的详细信息 5 define("APP_DEBUG",true);//上线时要关闭的 6 2.前端后台 7 App内Home复制一份,重命名Admin后台模块 8 如果有手机端可再复制一份Api模块 9 3.修改Admin/Controller/IndexController.class.php文件 10 namespace Admin\Cont

构建属于自己的ORM框架之二--IQueryable的奥秘

上篇文章标题乱起,被吐槽了,这次学乖了. 上篇文章中介绍了如何解析Expression生成对应的SQL语句,以及IQueryable的一些概念,以及我们所搭建的框架的思想等.但还没把它们结合并应用起来.这一篇文章将更黄更暴力,揭露IQueryable在实际使用中延迟加载的实现原理,结合上篇对Expression的解析,我们来实现一个自己的“延迟加载” 如果还不太了解如何解析Expression和IQueryable的一些基本概念,可以先看看我的上篇文章 我们先来做些基本工作,定义一个IDataB