Rafy 框架 - 执行SQL或存储过程

有时候,开发者不想通过实体来操作数据库,而是希望通过 SQL 语句或存储过程来直接访问数据库。Rafy 也提供了一组 API 来方便实现这类需求。

IDbAccesser 接口

为了尽量屏蔽各数据库中 SQL 语句参数的不同标识,同时也为了使开发者更简单地实现参数化的查询。Rafy 中提供了 IDbAccesser 接口来方便开发者使用。接口定义如下:

/// <summary>
/// A db accesser which can use formatted sql to communicate with data base.
/// </summary>
public interface IDbAccesser : IDisposable
{
    /// <summary>
    /// The underlying db connection
    /// </summary>
    IDbConnection Connection { get; }

    /// <summary>
    /// 数据连接结构
    /// </summary>
    DbConnectionSchema ConnectionSchema { get; }

    /// <summary>
    /// Gets a raw accesser which is oriented to raw sql and <c>IDbDataParameter</c>。
    /// </summary>
    IRawDbAccesser RawAccesser { get; }

    /// <summary>
    /// Execute a sql which is not a database procudure, return rows effected.
    /// </summary>
    /// <param name="formattedSql">a formatted sql which format looks like the parameter of String.Format</param>
    /// <param name="parameters">If this sql has some parameters, these are its parameters.</param>
    /// <returns>The number of rows effected.</returns>
    int ExecuteText(string formattedSql, params object[] parameters);

    /// <summary>
    /// Execute the sql, and return the element of first row and first column, ignore the other values.
    /// </summary>
    /// <param name="formattedSql">a formatted sql which format looks like the parameter of String.Format</param>
    /// <param name="parameters">If this sql has some parameters, these are its parameters.</param>
    /// <returns>DBNull or value object.</returns>
    object QueryValue(string formattedSql, params object[] parameters);

    /// <summary>
    /// Query out some data from database.
    /// </summary>
    /// <param name="formattedSql">a formatted sql which format looks like the parameter of String.Format</param>
    /// <param name="parameters">If this sql has some parameters, these are its parameters.</param>
    /// <returns></returns>
    IDataReader QueryDataReader(string formattedSql, params object[] parameters);

    /// <summary>
    /// Query out some data from database.
    /// </summary>
    /// <param name="formattedSql">a formatted sql which format looks like the parameter of String.Format</param>
    /// <param name="closeConnection">Indicates whether to close the corresponding connection when the reader is closed?</param>
    /// <param name="parameters">If this sql has some parameters, these are its parameters.</param>
    /// <returns></returns>
    IDataReader QueryDataReader(string formattedSql, bool closeConnection, params object[] parameters);

    /// <summary>
    /// Query out a row from database.
    /// If there is not any records, return null.
    /// </summary>
    /// <param name="formattedSql">a formatted sql which format looks like the parameter of String.Format</param>
    /// <param name="parameters">If this sql has some parameters, these are its parameters.</param>
    /// <returns></returns>
    DataRow QueryDataRow(string formattedSql, params object[] parameters);

    /// <summary>
    /// Query out a DataTable object from database by the specific sql.
    /// </summary>
    /// <param name="formattedSql">a formatted sql which format looks like the parameter of String.Format</param>
    /// <param name="parameters">If this sql has some parameters, these are its parameters.</param>
    /// <returns></returns>
    DataTable QueryDataTable(string formattedSql, params object[] parameters);

    /// <summary>
    /// Query out a row from database.
    /// If there is not any records, return null.
    /// </summary>
    /// <param name="formattedSql">a formatted sql which format looks like the parameter of String.Format</param>
    /// <param name="parameters">If this sql has some parameters, these are its parameters.</param>
    /// <returns></returns>
    LiteDataRow QueryLiteDataRow(string formattedSql, params object[] parameters);

    /// <summary>
    /// Query out a DataTable object from database by the specific sql.
    /// </summary>
    /// <param name="formattedSql">a formatted sql which format looks like the parameter of String.Format</param>
    /// <param name="parameters">If this sql has some parameters, these are its parameters.</param>
    /// <returns></returns>
    LiteDataTable QueryLiteDataTable(string formattedSql, params object[] parameters);
}

该接口使用类似于 String.Format 中的字符串格式来表达 SQL 中的参数。并在连接不同的数据库时,生成相应数据库对应的参数格式。

具体使用方法如下:

执行查询代码示例:

var bookRepo = RF.Concrete<BookRepository>();
using (var dba = DbAccesserFactory.Create(bookRepo))
{
    DataTable table = dba.QueryDataTable("SELECT * FROM Books WHERE id > {0}", 0);
}

执行非查询代码示例:

var bookRepo = RF.Concrete<BookRepository>();
using (var dba = DbAccesserFactory.Create(bookRepo))
{
    int linesAffected = dba.ExecuteText("DELETE FROM Books WHERE id > {0}", 0);
}

另外,DbAccesserFactory 中也提供了不通过仓库对象,而直接使用‘数据库连接的配置名’进行构建的方法,例如:

using (var dba = DbAccesserFactory.Create("JXC"))
{
    int linesAffected = dba.ExecuteText("DELETE FROM Books WHERE id > {0}", 0);
}

参数过多时,则依次按顺序传入即可:

using (var dba = DbAccesserFactory.Create(bookRepo))
{
    for (int i = 0; i < 10; i++)
    {
        dba.ExecuteText(
        "INSERT INTO Book (Author,BookCategoryId,BookLocId,Code,Content,Name,Price,Publisher) VALUES ({0},{1},{2},{3},{4},{5},{6},{7})",
        string.Empty,
        null,
        null,
        string.Empty,
        string.Empty,
        i.ToString(),
        null,
        string.Empty
        );
    }
}

IRawDbAccesser 接口

由于 IDbAccesser 接口封装了 SQL 语句中参数对应不同数据库中名称的变化,同时也更方便开发者使用,所以一般情况下,都推荐使用该接口。但是,IDbAccesser 接口并不支持存储过程的调用。另外,有时开发者希望自己来构建原生的 SQL 语句和参数,这时,就需要用到 IRawDbAccesser 接口了。(接口定义过长,这里不再贴出。)

该接口的使用方法与 IDbAccesser 类似,不同的地方在于 SQL 中需要传入特定数据库的参数名,并且参数需要自行构造,例如:

using (var dba = DbAccesserFactory.Create(bookRepo))
{
    for (int i = 0; i < 10; i++)
    {
        dba.RawAccesser.ExecuteText(
            "INSERT INTO Book (Author,BookCategoryId,BookLocId,Code,Content,Name,Price,Publisher,Id) VALUES ('', NULL, NULL, '', '', :p0, NULL, '', :p1)",
            dba.RawAccesser.ParameterFactory.CreateParameter("p0", i),
            dba.RawAccesser.ParameterFactory.CreateParameter("p1", i)
            );
    }
}

另外,IRawDbAccesser 接口也可以使用存储过程了,例如:

using (var dba = DbAccesserFactory.Create(bookRepo))
{
    for (int i = 0; i < 10; i++)
    {
        dba.RawAccesser.ExecuteProcedure(
            "InsertBookProcedure",
            dba.RawAccesser.ParameterFactory.CreateParameter("p0", i),
            dba.RawAccesser.ParameterFactory.CreateParameter("p1", i)
            );
    }
}

PS:该文已经纳入《 Rafy 用户手册》中。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏转载gongluck的CSDN博客

ADO大总结

内容比较乱,作为草稿,对现有的ado数据库操作函数方法进行汇总。 小函数 m_pRecordset->RecordCount//取得记录数量 全局变量 #i...

2958
来自专栏张善友的专栏

性能计数器数据收集服务

本文演示了一个Windows服务收集性能计数器的数据,将性能计数器数据写入数据库。Windows服务中调用WebAPI服务中。下面简要介绍下我的改造,项目虽小,...

2508
来自专栏Java帮帮-微信公众号-技术文章全总结

Hibernate_day03总结

Hibernate_day03总结 今日内容 l Hibernate的检索方式 l Hibernate的抓取策略 l Hibernate的批量检索 l 事务的并...

2423
来自专栏王亚昌的专栏

实战设计模式系列-Singleton(单件)

    单件模式的应用场景大家都不陌生,目的也很明确,就是一个类保证只有一个实际,比如项目中的资源管理器,或打log的类,都比较适合单件模式,话不多说,先贴一段...

701
来自专栏乐沙弥的世界

绑定变量及其优缺点

    绑定变量是Oracle解决硬解析的首要利器,能解决OLTP系统中library cache的过度耗用以提高性能。然刀子磨的太快,使起来锋利,却容 易折...

1012
来自专栏小尘哥的专栏

mybatis plus分页查询之掉坑里

当我们调用他service自带的selectPage(Page page, Wrapper wrapper)时候,有可能会有惊喜。比如

641
来自专栏菩提树下的杨过

silverlight的独立存储

这个东西有点象Flash的Cookie,可以用来在客户端存储一些数据,我在官方文档上读到这个功能的第一反应就是:用它来做IM的客户端聊天记录存储太棒了,呵呵 ...

2145
来自专栏Java技术分享

Hibernate 的性能优化的时候碰到了"抓取策略",有四种

    所以到处找资料, 但是无论从一些讲 Hibernate 书籍,还是他人 Blog 中都没有找到详细

2857
来自专栏JavaQ

三分钟学习分布式ID方案

在分布式系统中,当数据库数据量达到一定量级的时候,需要进行数据拆分、分库分表操作,传统使用方式的数据库自有的自增特性产生的主键ID已不能满足拆分的需求,它只能保...

1222
来自专栏数据库

干货!超过500行的Mysql学习笔记

本文为作者初学Mysql时做的笔记,囊括了Mysql相关基本知识,内容较多超过500行笔记,希望对大家有帮助。 ? /* 启动MySQL */ net star...

2186

扫码关注云+社区

领取腾讯云代金券