支持多数据库。报表可以定义使用的数据库,使用myjs.GetDAta方法获取数据。

This commit is contained in:
falcon 2021-05-31 15:11:06 +08:00
parent 57d7a71932
commit 92abb7e2de
9 changed files with 149 additions and 31 deletions

View File

@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using Falcon.StoredProcedureRunner;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.Extensions.Logging;
using ReportService.Database;
using ReportService.Models;
using ReportService.Models.ReportApi;
namespace ReportService.Controllers.api
{
@ -16,9 +15,8 @@ namespace ReportService.Controllers.api
public class ReportApiController:Controller
{
public IWebHostEnvironment Env { get; private set; }
public RSDbContext Db { get; set; }
public ILogger Logger { get; set; }
public IRunner DbRunner { get; set; }
public DbContextFactory DbFactory { get; set; }
/// <summary>
/// 报表存放位置
@ -29,11 +27,10 @@ namespace ReportService.Controllers.api
}
}
public ReportApiController(ILogger<ReportApiController> logger,IWebHostEnvironment env,RSDbContext db,IRunner r) {
public ReportApiController(ILogger<ReportApiController> logger,IWebHostEnvironment env,DbContextFactory dbFactory) {
this.Logger = logger;
this.Env = env;
this.Db = db;
this.DbRunner = r;
this.DbFactory = dbFactory;
}
/// <summary>
@ -123,8 +120,19 @@ namespace ReportService.Controllers.api
/// <param name="sql">要执行的sql语句</param>
/// <returns>json对象</returns>
public object GetResult(string sql) {
var result = this.DbRunner.RunRaw(this.Db,sql);
this.Logger.LogInformation($"GetResult:\n{sql}\n{result}");
return GetData(new GetDataData {
DbName = "ReportService",
Sql = sql,
});
}
/// <summary>
/// 从数据请求数据。
/// </summary>
/// <param name="data">请求数据模型</param>
/// <returns>返回json格式数据</returns>
public object GetData([FromBody]GetDataData data) {
var result = this.DbFactory.RunRawSql(data.DbName,data.Sql);
this.Logger.LogInformation($"GetData:\n{data.Sql}\n{result}");
return Content(result,"application/json; charset=utf-8");
}

View File

@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using Falcon.StoredProcedureRunner;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
namespace ReportService.Database
{
/// <summary>
/// 数据库上下文工厂
/// </summary>
public class DbContextFactory
{
/// <summary>
/// 数据库上下文集合
/// </summary>
public Dictionary<string,DbContextOptions> List { get; set; } = new();
/// <summary>
/// 数据库执行器
/// </summary>
public IRunner DbRunner { get; set; }
/// <summary>
/// 通过提供配置节点实例化数据库上下文工厂
/// </summary>
/// <param name="config">配置节点</param>
/// <param name="runner">数据库语句执行器</param>
public DbContextFactory(IConfigurationSection config,IRunner runner) {
foreach(var item in config.GetChildren()) {
DbContextOptionsBuilder builder = new();
builder.UseSqlServer(item.Value);
this.List.Add(item.Key,builder.Options);
}
this.DbRunner = runner;
}
/// <summary>
/// 获取数据库上下文
/// </summary>
/// <param name="name">节点定义的数据库名称</param>
/// <returns>数据上下文</returns>
public DbContext GetContext(string name) {
if(List.TryGetValue(name,out var option)) {
return new DbContext(option);
}
throw new Exception("使用的数据库名称错误!");
}
/// <summary>
/// 在指定数据库上执行原始sql语句并返回json格式数据。注意防止sql注入攻击
/// </summary>
/// <param name="dbName">数据库名称</param>
/// <param name="sql">要执行的sql语句</param>
/// <returns>json格式的数据库返回数据</returns>
public string RunRawSql(string dbName,string sql) {
if(this.DbRunner == null) {
throw new Exception("执行器注册错误没有实例化IRunner执行器");
}
return this.DbRunner.RunRaw(GetContext(dbName),sql);
}
}
}

View File

@ -0,0 +1,27 @@
using Falcon.StoredProcedureRunner;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace ReportService.Database
{
/// <summary>
/// 数据上下文工厂服务集合扩展
/// </summary>
public static class DbContextFactoryServiceCollectionEx
{
/// <summary>
/// 注册数据库工厂
/// </summary>
/// <param name="services">服务集合</param>
/// <param name="sectionKey">配置文件节点</param>
/// <returns>服务集合</returns>
public static IServiceCollection AddDbContextFactory(this IServiceCollection services,string sectionKey) {
services.AddSingleton(sp => {
var section = sp.GetService<IConfiguration>().GetSection(sectionKey);
var runner = sp.GetService<IRunner>();
return new DbContextFactory(section,runner);
});
return services;
}
}
}

View File

@ -1,14 +0,0 @@
using Microsoft.EntityFrameworkCore;
namespace ReportService.Database
{
/// <summary>
/// 报表服务数据库
/// </summary>
public partial class RSDbContext:DbContext
{
public RSDbContext(DbContextOptions options) : base(options) {
}
}
}

View File

@ -0,0 +1,17 @@
namespace ReportService.Models.ReportApi
{
/// <summary>
/// 请求数据模型
/// </summary>
public class GetDataData
{
/// <summary>
/// 要请求数据的数据库
/// </summary>
public string DbName { get; set; }
/// <summary>
/// 要执行的查询语句
/// </summary>
public string Sql { get; set; }
}
}

View File

@ -33,7 +33,4 @@
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Folder Include="Database\" />
</ItemGroup>
</Project>

View File

@ -21,10 +21,9 @@ namespace ReportService
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
var connStr = this.Configuration.GetValue<string>("Database:ReportService");
services.AddDbContext<RSDbContext>(b => {
b.UseSqlServer(connStr);
});
//注册数据上下文工厂
services.AddDbContextFactory("Database");
//引入存储过程执行器
services.AddFalconSPRunner();

View File

@ -8,7 +8,8 @@
},
"AllowedHosts": "*",
"Database": {
"ReportService": "Server=.\\SQLSERVER2008R2;Database=EASY_HEALTHRECORDS;User ID=sa;Password=111"
"ReportService": "Server=.\\SQLSERVER2008R2;Database=EASY_HEALTHRECORDS;User ID=sa;Password=111",
"test": "Server=.\\SQLSERVER2008R2;Database=EASY_HEALTHRECORDS;User ID=sa;Password=111"
},
"urls": "http://*:9000;https://*:9001"
}

View File

@ -6,6 +6,7 @@ var myjs = {
fileContentUrl: "/api/ReportApi/GetHtml",
reportUrl: "/api/ReportApi/GetPrint",
getresult: "/api/ReportApi/GetResult",
getData: "/api/ReportApi/GetData",
GetServerTime: "/api/ReportApi/GetServerTime",
},
//定义从对象获取请求参数的方法
@ -56,6 +57,27 @@ var myjs = {
.then(sc)
.catch(ec);
},
//从数据库获取数据。
getData(dbName, sql, sc, ec) {
if (!ec) {
ec = function (e) {
console.log(e);
alert(e);
};
}
if (!sc) {
sc = function (d) { console.log(d); };
}
var url = this.urls.getData;
var rd = { DbName: dbName, Sql: sql, };
fetch(url, {
method: 'POST',
body: JSON.stringify(rd),
headers: new Headers({
'Content-Type': 'application/json'
})
}).then(res => res.json()).catch(ec).then(sc);
},
//提示消息并记录
showmsg(msg) {
console.log(msg);