📚
Hoa Framework
  • 一、框架指南
  • 二、功能特性
  • 三、源码结构
  • 四、代码规范
  • 五、入门指南
  • 六、依赖注入/控制反转
  • 七、控制器和服务
  • 八、对象映射指南
  • 九、数据库操作指南
    • 9.1、正向工程(Code First)
    • 9.2、逆向工程(Database First)
    • 9.3、关于仓储(IRepository)
    • 9.4、增删改操作
    • 9.5、查询操作
    • 9.6、DataSet、DataTable 操作
    • 9.7、查询结果集映射
    • 9.8、批量增删改操作
    • 9.9、存储过程、视图、函数操作
    • 9.10、工作单元和事务
    • 9.11、多上下文、读写分离
    • 9.12、切面上下文(TangentDbContext)
    • 9.13、其他操作
    • 9.14、EF Core 高性能
    • 9.15、常见错误
  • 十、开放接口指南
    • 10.1、RESTFul 和 Swagger
    • 10.2、规范化返回值
  • 十一、数据校验
  • 十二、安全授权
  • 十三、异常处理
  • 十四、日志管理
  • 十五、配置管理
  • 十六、缓存管理
  • 十七、内置工具类
    • 17.1、数据加解密
  • 十八、跨域处理
  • 十九、筛选拦截器(未)
  • 二十、进程服务(Daemon)
  • 二十一、编写测试
    • 20.1、单元测试
    • 20.2、基准测试
    • 20.3、性能测试
  • 二十二、托管部署
    • 22.1、IIS 托管部署
    • 22.2、Nginx 托管部署
    • 22.3、Docker 容器部署
  • 二十三、性能分析(MiniProfiler)
  • 二十四、其他功能
    • 23.1、第三方包管理
    • 23.2、文件上传下载
    • 23.3、Razor 视图引擎
    • 23.4、生成客户端请求代码
    • 23.5、快捷操作
  • 二十五、Docker 容器化
    • 25.1、Docker 介绍
    • 25.2、Docker 安装
    • 25.3、Docker 安装服务
    • 25.4、Docker 常用命令
    • 25.6、Docker run 常用命令
    • 25.7、Docker-Compose 介绍
    • 25.8、docker-compose.yml
    • 25.9、Docker-Compose 常用命令
    • 25.10、Docker-Compose 转换 docker run
    • 25.11、Docker 构建自己的镜像
    • 25.12、Dockerfile指南
    • 25.13、Dockerfile 常用命令
    • 25.14、Dockerfile 打包、上传、分享
    • 25.15、Docker 数据卷
    • 25.16、Docker 域网络
    • 25.17、Docker + Nginx 实现分布式集群、负载均衡
  • 二十六、DevOps 持续部署集成
    • 26.1、DevOps 介绍
    • 26.2、持续集成、交付、部署
    • 26.3、Jenkins 介绍
    • 26.4、Jenkins 安装
    • 26.5、Jenkins 初始化
    • 26.6、Jenkins 实战演练
    • 26.7、Jenkis 项目配置
    • 26.8、Jenkins 插件
  • 二十七、OpenXml/Excel 操作
  • 二十八、SaaS 多租户
  • 二十九、Git 代码管理
    • 29.1、Git 介绍
    • 29.2、Git 安装
    • 29.3、Git 基础配置
    • 29.4、Git 工作流程
    • 29.5、Git 重要概念
    • 29.6、Git 创建仓库
    • 29.7、Git 基本操作
    • 29.8、Git 分支管理
    • 29.9、Git 查看提交历史
    • 29.10、Git 标签
    • 29.11、Git 拉取/获取/推送
    • 28.12、Git GUI工具
    • 29.13、Git 私有化部署
    • 29.14、Git 推荐开发模式
    • 29.15、Svn 转 Git
  • 贡献代码
  • 更新日志
由 GitBook 提供支持
在本页
  • 存储过程
  • 无需配置 DbSet 方式调用存储过程(推荐)
  • 配置 DbSet 方式调用存储过程
  • 存储过程参数说明
  • 视图
  • 配置视图DbSet
  • 视图使用
  • 函数
  • 函数直接调用
  • 数据库内置函数使用
  • 自定义标量函数

这有帮助吗?

  1. 九、数据库操作指南

9.9、存储过程、视图、函数操作

存储过程、视图、函数操作是关系型数据库处理复杂逻辑的强大辅助。

上一页9.8、批量增删改操作下一页9.10、工作单元和事务

最后更新于4年前

这有帮助吗?

存储过程

在Hoa Framework v1.4.0 版本新增了 切面上下文功能,也就是下面的代码不再推荐使用,见 章节。

无需配置 DbSet 方式调用存储过程(推荐)

正常情况下,存储过程也需要和实体一样,需要配置 DbSet 和 ,而且只能返回指定存储过程指定的返回实体模型,这样比较繁琐。()

所以,Hoa Framework 提供了更加简便的方式。支持返回任意数据类型。代码如下:

// 返回存储过程实体模型
_testRepository.SqlProcedureQuery<PROC_Entity>(DbConsts.Procedure.PROC_NAME_KEY, new (){});

// 返回任意类型
_testRepository.SqlProcedureQuery<int>(DbConsts.Procedure.PROC_NAME_KEY, new (){})

这种方式最大的好处就是可使用任何仓储对象进行执行存储过程,是极速开发推荐方式。

配置 DbSet 方式调用存储过程

在Hoa Framework v1.4.0 版本新增了 切面上下文功能,也就是下面的代码不再推荐使用,见 章节。

由于存储过程是,所以,需要手动配置 DbSet 和 创建存储过程返回值 Entity 模型。

在 Hoa Framework 框架中,需要手动配置在 Hoa.EntityFramework.Core.ManualHoaDbContext.cs 文件中,避免被 Database First 生成器每次生成后覆盖掉。代码如下:

using Microsoft.EntityFrameworkCore;
using System;
using Hoa.Core;

namespace Hoa.EntityFrameworkCore
{
    public partial class HoaDbContext
    {
        // PROC_Entity 是存储过程返回值对应的实体模型
        public virtual DbSet<PROC_Entity> PROC_Entities { get; set; }

        partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
        {
            // 配置存储过程无键实体模型
            modelBuilder.Entity<PROC_Entity>(entity =>
            {
                entity.HasNoKey();
                // 通常我们需要将存储过程名称作为常量定义起来
                // 这里的存储过程名称配置在 Hoa.Core.DbConsts.cs 文件中
                entity.ToView(DbConsts.Procedure.PROC_NAME_KEY);
            });
        }
    }
}

通过上述配置后,即可通过 IRepository<PROC_Entity> 获得存储过程操作仓储对象,然后调用 FromSql 方式调用存储过程。如:

// DbConsts.Procedure.PROC_NAME_KEY 仓储过程名称
// 第二个参数为存储过程的参数
_procEntityRepository.FromSql(DbConsts.Procedure.PROC_NAME_KEY, new (){});

这种方式只能返回指定存储过程指定的返回实体模型。

存储过程参数说明

由于存储过程存在参数且参数名可能和参数模型不一致,所以 Hoa Framework 内置了强大存储过程参数配置特性。

默认情况下,我们可以通过 匿名对象 作为存储过程的参数,这种做法的好处就是无需创建一个 存储过程参数模型,但是缺点也显而易见,就是必须严格按照存储过程定义的参数排序进行传入。而且匿名对象属性名也必须和存储过程参数名一一对应。

所以,Hoa Framework 建议开发者使用强类型模型作为存储过程参数模型,这样无需考虑排序,又能指定存储过程参数名称。

_testRepository.SqlProcedureQuery<PROC_Entity>("存储过程名"
                , new ProcModel(){ Name = "Hoa", Age = 27 });
using Hoa.DbManager.Attributes;
using System;
using System.Collections.Generic;
using System.Text;

namespace Hoa.Core.Utilities.Entities
{
    public class ProcModel
    {
        // 可以指定存储过程实际参数名
        [ProcedureParameter("ACCOUNT_NAME")]
        public string Name { get; set; }
        
        public string Age { get; set; }
    }
}

这种方式可维护性强,也利于拓展。

视图

配置视图DbSet

在 Hoa Framework 框架中,需要手动配置在 Hoa.EntityFramework.Core.ManualHoaDbContext.cs 文件中,避免被 Database First 生成器每次生成后覆盖掉。代码如下:

using Microsoft.EntityFrameworkCore;
using System;
using Hoa.Core;

namespace Hoa.EntityFrameworkCore
{
    public partial class HoaDbContext
    {
        // VIEW_Entity 是视图返回值对应的实体模型
        public virtual DbSet<VIEW_Entity> VIEW_Entities { get; set; }

        partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
        {
            // 配置视图无键实体模型
            modelBuilder.Entity<PROC_Entity>(entity =>
            {
                entity.HasNoKey();
                // 通常我们需要将视图名称作为常量定义起来
                // 这里的视图配置在 Hoa.Core.DbConsts.cs 文件中
                entity.ToView(DbConsts.TableView.VIEW_NAME_KEY);
            });
        }
    }
}

通过上述配置后,即可通过 IRepository<VIEW_Entity> 获得视图仓储对象,之后就可以使用仓储中除了 增删改 以外的操作了!通常视图只用作查询和权限控制。如:

视图使用

// 查询操作
_tableViewRepository.Entity.Where(u => u.Id == 1 && u.Name.Contains("Hoa"));

_tableViewRepository.Entity
    .Where(u => u.Void == 0)
    .WhereIf(!string.IsNullOrEmpty(name),u => u.Name.Contains(name))
    .WhereIf(age > 18,u => u.Age == age)
    .Where(u => u.Field > 20);

函数

数据库中函数的调用非常简单,无需配置 DbSet 模型,也无需创建特定的 IRepository<> 仓储对象。

函数直接调用

_repository.SqlScalarFunctionQuery<返回值类型>("方法名称",new FunctionModel{});

// 还可以指定返回值列名
_repository.SqlScalarFunctionQuery<返回值类型>("方法名称",new FunctionModel{},"指定结果集列名");

注意:这种方式只能单纯的输出函数的返回值,并不能联合 sql 进行查询。

数据库内置函数使用

EF Core 为我们提供了很多常用的内置函数,可以在 Lambda 条件中使用,主要是通过 EF.Functions 调用,如:

_testRepository.Entity
    .Where(u => EF.Functions.DateDiffHour(u.CreatedDt, DateTime.Now) > 8)
    .FirstOrDefault();

这个语句使用了 EF.Functions.DateDiffHour 最终生成的 Sql 如下:

SELECT TOP(1) [a].*
FROM [dbo].[TEST] AS [a]
WHERE DATEDIFF(HOUR, [a].[CREATED_DT], GETDATE()) > 8

也就是生成了对应 DATEDIFF 函数。

自定义标量函数

这个有区别与上面的 函数调用,上面的 函数调用 只能用于单纯的调用函数,并不能在 Lambda 语句中使用。

而通过自定义标量函数的方式,可以实现在 Lambda 和 Linq 中调用。

假设我们数据库有一个自定义标量函数:

CREATE FUNCTION FN_GET_YEAR
(
	@DATE DATETIME
)
RETURNS VARCHAR(100)
AS
BEGIN
	RETURN YEAR(@DATE)
END

接下来

第一步:我们需要在 Hoa.Core.DbScalarFunctions.cs 中申明:

using Microsoft.EntityFrameworkCore;
using System;

namespace Hoa.Core
{
    public static class DbScalarFunctions
    {
        // Name 为 数据库标量函数中真实的名称(必填)
        // Schema 为 数据库标量函数所在的 Schema(必填)
        [DbFunction(Name = "FN_GET_YEAR", Schema = "dbo")]
        public static string GetYear(DateTime date) => throw new NotSupportedException();
    }
}

第二步:需要在 Hoa.EntityFramework.Core.ManualHoaDbContext.cs 中配置中初始化:

using Microsoft.EntityFrameworkCore;
using System;
using Hoa.Core;

namespace Hoa.EntityFrameworkCore
{
    public partial class HoaDbContext
    {
        partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
        {
            // 注意:如果你的函数有多少个参数,就填写多少个 default 
            modelBuilder.HasDbFunction(() => DbScalarFunctions.GetYear(default));
        }
    }
}

配置好上面两步后,就可以使用该函数了:

_testRepository.Entity
    .Where(u => DbScalarFunctions.GetYear(u.CreatedDt) == "2020")
    .FirstOrDefault();

最终生成的 Sql 如下:

SELECT TOP(1) [a].*
FROM [dbo].[TEST] AS [a]
WHERE [dbo].[FN_GET_YEAR]([a].[CREATED_DT]) = N'2020'

这种自定义标量函数除了可以在 Where 条件中调用,还能在 Select 结果集中使用。如:

_testRepository.Entity
    .Where(u => DbScalarFunctions.GetYear(u.CreatedDt) == "2020")
    .Select(u => new { Year = DbScalarFunctions.GetYear(u.CreatedDt) })
    .FirstOrDefault();

示例一:参数模型和存储过程名字一致

示例二:指定存储过程的实际参数,在存储过程参数模型中设置

视图是一张虚拟表,也是,所以,需要手动配置 DbSet 和 创建视图返回值 Entity 模型,这一点和存储过程配置无异。

更多视图仓储的操作可查看 文档。

在Hoa Framework v1.4.0 版本新增了 切面上下文功能,也就是下面的代码不再推荐使用,见 章节。

更多内置的EF函数。

🏴
🏴
9.12、切面上下文(TangentDbContext)
无键实体类型
见 DbSet 方式
9.12、切面上下文(TangentDbContext)
无键实体类型
无键实体类型
9.5、查询操作
9.12、切面上下文(TangentDbContext)
可查看官方文档