Furion框架
上一章写到如何创建 Furion 模板和脚手架安装以及EF 搭建和自动生
成实体
这一章写一下,如何配置配置文件以及 Application层的 Services和 Core层的Model 和 Repository 做接口调用
拿上一章创建的 HelloBlog FurionAPI来说
当创建好项目搭建好EF,下面就让程序跑起来
一、在 HelloBlog.Web.Entry 更改配置文件 appsettings.json
DbConnectionString 连接的字符串
{
"ConnectionStrings": {
//"DbConnectionString": "Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;",
"DbConnectionString": "Server=.;database=Test_Demo;Trusted_Connection=True;MultipleActiveResultSets=True;",
"Sqlite3ConnectionString": "Data Source=./Test_Demo.db"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"Microsoft.EntityFrameworkCore": "Information"
}
},
"AllowedHosts": "*"
}
二、在Program 文件 IHostBuilder方法中 添加.Inject() 依赖注册
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace HelloBlog.Web.Entry
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.Inject()
.UseStartup<Startup>();
});
}
}
三、在HelloBlog.EntityFramework.Core 层我们需要配置 默认生成的 DefaultDbContext.cs
①设置 [AppDbContext(“数据库连接字符串或者键”, DbProvider.SqlServer【一定要指明数据库类型】)]
② 有的表字段为空需要允许为空 InsertOrUpdateIgnoreNullValues = true; //忽略空值
using Furion.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;
namespace HelloBlog.EntityFramework.Core
{
[AppDbContext("DbConnectionString", DbProvider.SqlServer)]
public class DefaultDbContext : AppDbContext<DefaultDbContext>
{
public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)
{
InsertOrUpdateIgnoreNullValues = true; //忽略空值
}
}
}
四、根据上一章在 HelloBlog.Core 中我们搭建了 EF 自动生成了实体,我们还需要建一个文件夹用于 Repository 的业务逻辑
①在刚创建的 Repository 文件夹下面 添加Repository. 我这里是 SySDepartmentRepository.sc
Repository编写业务逻辑
using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Microsoft.EntityFrameworkCore;
namespace HelloBlog.Core.Repository
{
public static class SySDepartmentRepository
{
//新增操作
public static void InsertDepartment(this IRepository<SySDepartment> repository, SySDepartment sysdepartment)
{
//同步操作
repository.Insert(sysdepartment);
//或者 sysdepartment.Insert();
//或者 repository.Entities.Add(sysdepartment);
//或者 repository.ChangeEntityState(sysdepartment, EntityState.Added);
}
public static List<SySDepartment> GetDepartments(this IRepository<SySDepartment> repository, string facility)
{
return repository.Where(u => u.Facility.Equals(facility)).ToList();
}
//复杂的SQL语句查询
public static string GetTreedata(this IRepository<SySDepartment> repository, string facility, string site, string language)
{
//树形菜单绑定
string str = $@"
IF NOT OBJECT_ID(N'Tempdb..#T2') IS NULL
DROP TABLE #T2;
SELECT R.id, DE.DEPT_CODE ,
VA.MEANING AS name ,
DE.UPPER_DEPT,
R1.parentId,
LINE_ID,
ISNULL(DE.MODIFY_DATE,ISNULL(VA.MODIFY_DATE,ISNULL(R.MODIFY_DATE,ISNULL(R1.MODIFY_DATE,DE.CREATE_DATE)))) AS UP_DATE
INTO #T2
FROM SY_S_DEPARTMENT DE
INNER JOIN SY_S_GLOBAL_MULTIPLE_LANGUAGE_VALUE VA ON DE.DEPT_CODE = VA.LOOKUP_VALUE
INNER JOIN ( SELECT ROW_NUMBER() OVER ( ORDER BY CREATE_DATE,DEPT_CODE ASC ) AS id ,
DEPT_CODE,MODIFY_DATE
FROM SY_S_DEPARTMENT
) AS R ON R.DEPT_CODE = DE.DEPT_CODE
LEFT JOIN ( SELECT ROW_NUMBER() OVER ( ORDER BY CREATE_DATE,DEPT_CODE ASC ) AS ParentId ,
DEPT_CODE,MODIFY_DATE
FROM SY_S_DEPARTMENT
) AS R1 ON R1.DEPT_CODE = DE.UPPER_DEPT
WHERE VA.LANGUAGE = '{language}' --'zh-cn'
AND DE.FACILITY='{facility}'
AND DE.SITE='{site}';
--递归
WITH menu ( id, name, DEPT_CODE, UPPER_DEPT, parentId,LINE_ID,UP_DATE, Level, px, px2 )
AS ( SELECT id ,
name ,
DEPT_CODE ,
UPPER_DEPT ,
parentId ,
LINE_ID,
UP_DATE,
0 AS Level ,
id px ,
CAST(id AS NVARCHAR(4000)) px2
FROM #T2
WHERE parentId IS NULL
UNION ALL
SELECT A.id ,
A.name ,
A.DEPT_CODE ,
A.UPPER_DEPT ,
A.parentId ,
A.LINE_ID,
A.UP_DATE,
B.Level + 1 ,
B.px ,
B.px2 + LTRIM(A.id)
FROM #T2 A
INNER JOIN menu B ON A.parentId = B.id
)
SELECT id ,
name ,
DEPT_CODE ,
UPPER_DEPT ,
CASE WHEN parentId IS NULL AND DEPT_CODE='DO' AND id=1 THEN 0
WHEN parentId IS NULL AND DEPT_CODE <>'DO'AND id<>1 THEN 1
ELSE parentId
END AS parentId ,
LINE_ID,
Level ,
px ,
px2
FROM menu
ORDER BY LINE_ID ASC,UP_DATE DESC;";
//var list = str.SqlQuery().AsEnumerable().ToList();
//var dt = list.CopyToDataTable();
var dt = str.SqlQuery();
return JsonConvert.SerializeObject(dt);
}
}
}
以上InsertDepartment、GetDepartments、GetTreedata 三个方法将有 Services接口 调用,Repository 会以依赖注入方式
五、设置Services 接口方法 、在Services接口实现类中依赖注入Repository
Services 接口
using HelloBlog.Core;
namespace HelloBlog.Application
{
public interface ISystemService
{
string GetDescription();
void InsertDepartment(SySDepartment department);
string GetTree();
}
}
Services接口实现
//注入 _sysdepartmentRepository
private readonly IRepository _sysdepartmentRepository;
public SystemService(IRepository sysdepartmentRepository)
{
_sysdepartmentRepository = sysdepartmentRepository;
}
using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using HelloBlog.Core;
using HelloBlog.Core.Repository;
namespace HelloBlog.Application
{
public class SystemService : ISystemService, ITransient
{
//注入 _sysdepartmentRepository
private readonly IRepository<SySDepartment> _sysdepartmentRepository;
public SystemService(IRepository<SySDepartment> sysdepartmentRepository)
{
_sysdepartmentRepository = sysdepartmentRepository;
}
public string GetDescription()
{
return "让 .NET 开发更简单,更通用,更流行。";
}
public void InsertDepartment(SySDepartment department)
{
_sysdepartmentRepository.InsertDepartment(department);
}
public string GetTree()
{
//调用sysdepartmentRepository
var getdepartments = _sysdepartmentRepository.GetDepartments("APAT");
var gettreedatajson = _sysdepartmentRepository.GetTreedata("APAT", "SZ", "zh-cn");
return gettreedatajson;
}
}
}
方法 InsertDepartment、GetDepartments、GetTreedata 都是调用 ISystemService()
当注入Repository后 就可调用 Repository里面的InsertDepartment、GetDepartments、GetTreedata,实则调用的是 Repository里面的(前提是注入过)
_sysdepartmentRepository.InsertDepartment(department);
var getdepartments = _sysdepartmentRepository.GetDepartments("APAT");
var gettreedatajson = _sysdepartmentRepository.GetTreedata("APAT", "SZ", "zh-cn");
六、运行测试是否能取到数据,查看执行流程
测试GetTreedata 方法
已经进入到SystemAppService 的GetTreedata 方法中
顺利进入了SystemService 接口基础类上面了,接下来看是否进入注入的Repository 的GetTreedata方法中
已经进入GetTreedata 取到数据了
显示200
另外还可以直接启用
HelloBlog\HelloBlog.Core\bin\Debug\net5.0 下面的 HelloBlog.Web.Entry.exe 程序
然后我们可以访问
https://localhost:5001/api/system/Tree
这时候控制台出现 我访问方法所执行SQL 语句
浏览器也能展示出数据
需要unicode 解码就可以了
本章的demo