1 VScoed快捷键
2 基础
2.1 杂乱知识
所有 C# 类型(包括 int 和 double 等基元类型)均继承自一个根 object 类型。
C# 程序在 .NET 上运行,而 .NET 是名为公共语言运行时 (CLR) 的虚执行系统和一组类库。CLR 是 Microsoft 对公共语言基础结构 (CLI) 国际标准的实现。CLI 是创建执行和开发环境的基础,语言和库可以在其中无缝地协同工作。
程序集 -> CLR -> 实时编译 -> 本机指令
执行 C# 程序时,程序集将加载到 CLR。 CLR 会直接执行实时 (JIT) 编译,将 IL 代码转换成本机指令。
(CLR 可提供其他与自动垃圾回收、异常处理和资源管理相关的服务。 CLR 执行的代码有时称为“托管代码”。而“非托管代码”被编译成面向特定平台的本机语言。)
标识符是变量名称。如果标识符的前缀为 @,则该标识符可以是 C# 保留字。在与其他语言交互时,使用保留字作为标识符很有用。
2.2命令空间
命名空间提供了一种用于组织 C# 程序和库的分层方法。
2.3 类型和变量
2.3.1 值类型
强制转换的方法 : (数据类型名称) 变量名
string类的方法 :
String.Compare( strA,strB ) //比较
String.Concat(strA,strB) //链接
C# string 字符串的前面可以加 @(称作"逐字字符串")将转义字符(\)当作普通字符对待
@ 字符串中可以任意换行,换行符及缩进空格都计算在字符串长度之内。
2.3.2 引用类型
数组类型 : 先定义,后使用
int[] balance = new int[10];
balance[0] = 1;
balance[1] = 2;2.3.3 区分
class类型 : 包含数据成员、函数成员
struct类型 : 包含数据成员、函数成员的结构(结构是值类型,通常不需要进行堆分配。)
interface类型 : 将协定定义为一组已命名的公共成员。可以继承自多个基接口。由class或struct来实现
delegate 类型 : 表示引用包含特定参数列表和返回类型的方法。 通过委托,可以将方法视为可分配给变量并可作为参数传递的实体。类似“函数指针”
2.3.4 装箱 拆箱
int i = 123;
object o = i; // Boxing
int j = (int)o; // Unboxing将值类型的值分配给 object 对象引用时,会分配一个“箱”来保存此值。
当 object 引用被显式转换成值类型时,则会将箱中的值复制到值类型。
2.4 程序结构
组织结构概念包括程序、命名空间、类型、成员和程序集。
程序集的文件扩展名通常为 .exe 或 .dll
2.5 main函数
public static void Main() { }
public static int Main() { }
public static void Main(string[] args) { }
public static int Main(string[] args) { }
public static async Task Main() { }
public static async Task<int> Main() { }
public static async Task Main(string[] args) { }
public static async Task<int> Main(string[] args) { }添加 async、Task 和 Task<int> 返回类型可简化控制台应用程序需要启动时的程序代码,以及 Main 中的 await 异步操作。
2.6 输入输出
输出 (打印)
Console.WriteLine(); 输出内容,并换行
Console.Write(); 输出内容,不换行
输入(键盘输入)
Console.Read(); 从屏幕读取一个字符,并返回该字符所对应的整型数字
Console.ReadLine(); 从屏幕读取一串字符,并返回该字符串
int整数类型要将收入的字符串转化为int类型接收
int age=int.parse(Console.ReadLine());double类型要将收入的字符串转化为double类型接收
double length = double.parse(Console.ReadLine());解决打印字符 控制台 瞬间关闭的问题:
//在下边加入以下代码
//程序结束后等待用户按下任意键再关闭控制台窗口
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);输出的占位符
Console.Write("提示字符串内容:{0}",a);
占位符从零开始计数
2.7 封装
public:所有对象都可以访问;
private:对象本身在对象内部可以访问;
protected:只有该类对象及其子类对象可以访问
internal:同一个程序集的对象可以访问;
protected internal:访问限于当前程序集或派生自包含类的类型。

比如说:一个人A为父类,他的儿子B,妻子C,私生子D(注:D不在他家里)
如果我们给A的事情增加修饰符:
public事件,地球人都知道,全公开
protected事件,A,B,D知道(A和他的所有儿子知道,妻子C不知道)
private事件,只有A知道(隐私?心事?)
internal事件,A,B,C知道(A家里人都知道,私生子D不知道)
protected internal事件,A,B,C,D都知道,其它人不知道
2.8 方法
格式 :
修饰符 函数返回类型 函数名 (参数列表){
函数体
}
注意点:
方法要写在class类中
引用方法时,要使用 class名 变量名 = new class名(); 进行声明
//声明类
class Max
{
//方法写在类中
public int FindMax(int num1, int num2)
{
/* 局部变量声明 */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
}
internal class Program
{
static void Main(string[] args)
{
//main函数调用时,要先声明这个类,再调用其中的方法
Max max = new Max();
int c = max.FindMax(a, b);
}
}在 C# 中,使用 ref 关键字声明引用参数.引用参数表示与提供给方法的实际参数具有相同的内存位置。
注意 : 形参前要加ref,传递实参时也需要加ref
按输出传递参数 : return只能返回一个值 , 当想要得到两个返回值时, 可以使用out 来修饰形参,以得到多个返回值.
2.9 函数
构造函数 : 名称与类的名称完全相同,它没有任何返回类型。
析构函数 : 是类的一个特殊的成员函数,当类的对象超出范围时执行。在类的名称前加上一个波浪形(~)作为前缀,它不返回值,也不带任何参数。用于在结束程序(比如关闭文件、释放内存等)之前释放资源
2.10 继承
C# 不支持类的多重继承,但支持接口的多重继承,一个类可以实现多个接口。
概括来说:一个类可以继承多个接口,但只能继承自一个类。
格式 :
class A : B{
}
即A继承B (B为父类,A为子类)
2.11 多态
直接进行重写即可
2.12 特点
三目运算符
格式 : A ? B : C
意义 : 当a为真,则表达式值为b,如果a为假,则表达式值为c
datatype ?
如 int?:表示可空类型,就是一种特殊的值类型,它的值可以为null 用于给变量设初值得时候,给变量(int类型)赋值为null,而不是0
3. 项目结构
3.1 controller
实现的接口在这儿写
格式 :
//使用post请求,写入路由的名称,即接口调用时,浏览器中输入的名称
[HttpPost("RouteName")]
//函数返回类型是IActionResult(状态码),定义FunctionName(函数名),传入DTO类(目的是为了让用户传参)
public IActionResult FunctionName(DTO DTOName)
{
//DAO类的实例化(DAO是对数据库的封装,)
DAO DAOName = new DAO();
//将DTO的值赋给DAO(即将用户输入的信息,传给数据库的字段)
DAOName.Member = DTOName.Member;
......
//调用DAO方法(DAO继承TableModelMSSQL,故有其中的方法)
DAOName.Add();
DAOName.GetModel(" DepartmentID = 1");
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.Output("40000001")); //代表插入成功
}3.2 common
SysConstant : 系统常量. 比如SQL Server的配置字符串在此定义
DbHelperMSSQL: 操作数据库的类
UtilHelper : 操作辅助类
3.3 model
dao:
(data access object 数据访问对象) , 包含对数据的访问,负责持久层的操作 。封装数据库
格式:
using Tiliatech.IECS_API.Common;
using Tiliatech.IECS_API.Model.DAO;
namespace WebApplication2.Models.DAO
{
//首先要继承TableModelMSSQL(各种操作数据库的方法)
public class BaseUser :TableModelMSSQL
{
//定义构造方法,获取数据库名称
public BaseUser()
{
//UtilHelper是一个公用类,调用其中的获取数据库名称的方法
//GetColumns是TableModelMSSQL中的一个方法,传入数据库名称,传入表名称,得到数据库列
TableColumnMSSQLs = GetColumns(UtilHelper.DB_NAME, "Employees");
}
//定义成员
private int _EmployeeID;
private string _Name;
private int _DepartmentID;
//获取数据库字段
public int EmployeeID { get => _EmployeeID; set => _EmployeeID = value; }
public string Name { get => _Name; set => _Name = value; }
public int DepartmentID { get => _DepartmentID; set => _DepartmentID = value; }
}
}TableModelMSSQL中的方法 :
dto:
(Data Transfer Object 数据传输对象),表示用户信息的数据传输对象, 在进行请求时,应用在接口接收传入对象,然后又转换成实体进行持久化。在此过程中,传入的对象就是DTO.
如:
namespace WebApplication2.Models.DTO
{
public class UserDTO
{
public int EmployeeID { get; set; }
public string Name { get; set; }
public int DepartmentID { get; set; }
}
}调用逻辑 : 客户端发送请求 -> 顶级类 -> controller
4. webAPI
4.1 新建项目
ASP.NET Core Web API
4.2 controller下做接口
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace WebApplication2.Controllers
{
//1 . 声明接口
[ApiController]
//2. 一级接口路径(路由:api接口的路径)
[Route("test")]
// 3. 继承ControllerBase
public class TestController : ControllerBase
{
//4.添加接口的注释
///<summary>该接口的作用是什么</summary>
///<param name="形参名称">要传入的参数是什么</param>
///<returns>返回什么值</returns>
//5. 写接口
[HttpGet("getUsers")] //接口类型()中填写的是二级路径
//当一个动作中有多个ActionResult返回类型时,IActionResult返回类型是合适的。
//ActionResult类型代表各种HTTP状态代码。
public IActionResult ADSD()
{
return StatusCode(StatusCodes.Status400BadRequest, ("40000001"));
}
[HttpGet("getUserById")]
//如使用get请求获取参数,直接在该函数中定义形参即可
public int GetUserById(int id)
{
return id;
}
}
}4.3 路由设计
Route为api接口的路径
[controller]是所在文件的名称的前缀,如现在的文件名为TestController,则controller的值为Test
[action] 是函数方法的名称
[HttpGet("")] 或 [HttpPost("")] 或 [HttpPut("")] 或 [HttpPatch("")] 或 [HttpDelete("")] , 指定了接口的类型,()中也可填写路径
如 : 路由为[Route("api/[controller]/[action]")] , 后边跟有 [HttpPost("POST/employees")]
则会被拼接为
4.4 注解
[Authorize] : 完成一些简单的权限管理功能
[PermissionFilter] : 用于过滤权限的机制 . 在开发中,我们通常需要对不同用户或用户组进行权限控制,以确保不同角色只能访问其具备权限的资源或执行特定操作。
4.5 返回值
return StatusCode(StatusCodes.xxx, "");
4.6 执行
4.7 发布
右键 -> 发布
点击发布
5. 连接SQL Server
先导入库包
using System.Data; // 表的命名空间 using System.Data.SqlClient; // 和SQL相关的命名空间数据库配置信息
数据库名称 : MSSQLSERVER 使用SSMS连接时,输入的服务器名称 : DESKTOP-DKL\localhost 数据库用户名 : sa 数据库密码 : 123456
VS Code里下载nuGet包
System.Data.SqlClient
连接数据库
//定义一个字符串(里边包含数据库的配置项信息)
String sqlcon = "Server=服务器名; Database=数据库名; uid = 用户名; pwd = 密码; Trusted_Connection = False;"
//实例化数据库对象,传入配置项sqlcon
SqlConnection con = new SqlConnection(sqlcon);
//打开数据库
con.Open();本台电脑的配置如下:
Server=localhost; Database=TestBase; uid = sa; pwd = 123456; Trusted_Connection = False;
操作数据库
//定义sql语句
String sql = "sql语句";
//创建sql命令对象cmd,传入sql语句和数据库对象con
SqlCommand cmd = new SqlCommand(sql,con);
//创建sql接收器对象adapter,传入sql命令对象cmd //DataAdapter 是用于在 DataSet 和数据源之间进行数据交换的桥梁
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
//创建DataSet 对象ds,DataSet用于存储和处理数据
DataSet ds = new DataSet();
//adapter中的数据填充到ds当中,接下来即可通过 DataSet 对象(ds)来访问和操作从数据库中检索到的数据
adapter.Fill(ds);
//使用DataTable来接收查询结果
DataTable dt = ds.Tables[0]; //dt得到第一个表的数据
DataRow dr = dt.Rows[0]; //dr得到表中第一行数据
//验证查询结果
System.Console.WriteLine(dr["name"]); //输出第一行字段为name的值6. Restful API
6.1 URL 设计
客户端发出的数据操作指令都是"动词 + 宾语"的结构 , 如 /articles
若有些客户端只能使用GET和POST这两种方法 , 如何表示其他三个方法?
使用
POST模拟其他三个方法(PUT、PATCH、DELETE)。客户端发出的 HTTP 请求,要加上
X-HTTP-Method-Override属性POST /api/Person/4 HTTP/1.1 X-HTTP-Method-Override: PUT
注意点:
动词一律大写,宾语必须是名词.
如动词GET , 宾语articles
避免多级 URL . 最佳的做法是 : 除了第一级,其他级别都用查询字符串表达。
如GET /articles?published=true , 而不是GET /articles/published
6.2 状态码设计
客户端的每一次请求,服务器都必须给出回应。回应包括 HTTP 状态码和数据两部分。
6.2.1 2xx状态码 -> 操作成功
GET: 200 OK
POST: 201 Created
PUT: 200 OK
PATCH: 200 OK
DELETE: 204 No Content
POST返回201状态码,表示生成了新的资源;
DELETE返回204状态码,表示资源已经不存在。
202 Accepted状态码表示服务器已经收到请求,但还未进行处理,会在未来再处理,通常用于异步操作。
6.2.2 3xx状态码 -> 重定向
// 301/302重定向可以由应用级别返回,浏览器会直接跳转,API 级别可以不考虑这两种情况。这种是直接跳转
303 是API 用到的状态码,表示参考另一个 URL。浏览器不会自动跳转,而会让用户自己决定下一步怎么办。
6.2.3 4xx状态码 -> 客户端错误
6.2.4 5xx状态码 -> 服务器错误
API 不会向用户透露服务器的详细信息,所以只要两个状态码就够了。
6.3 服务器回应
6.3.1 服务器要返回JSON对象
API 返回的数据格式,不应该是纯文本,而应该是一个 JSON 对象
服务器回应的 HTTP 头的
Content-Type属性要设为application/json客户端请求时,也要告知服务器可以接受 JSON 格式,即请求的 HTTP 头的
ACCEPT属性也要设成application/json
IHttpActionResult是WebApi最常用的一种返回值类型,常用的方式有:Json(T content)、Ok()、 Ok(T content)、NotFound()、Content(HttpStatusCode statusCode, T value)、BadRequest()、Redirect(string location)等
6.3.2 正确使用状态码
错误做法 : 即使发生错误,还返回200状态码,把错误信息放在数据体里面
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "failure",
"data": {
"error": "Expected at least two items in list."
}
}正确做法 : 状态码反映发生的错误,具体的错误信息放在数据体里面返回
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "Invalid payoad.",
"detail": {
"surname": "This field is required."
}
}6.3.3 提供API链接
HATEOAS方法 : 在回应中,给出相关链接,便于下一步操作。用户只要记住一个 URL,就可以发现其他的 URL。
如GitHub 的 API 都在 api.github.com 这个域名
[Route("api/[controller])]
[Route("api/[action]")]
7. 数据库构建
创建数据库
CREATE TABLENAME
(
字段1 dataType primary key,
字段1 dataType,
字段1 dataType,
字段1 dataType,
字段1 dataType
);主键字段自增操作
先创建一个序列
CREATE SEQUENCE name_seq;到主键上 , 进行绑定序列
nextval('name_seq'::regclass)
8. model数据库表对象模版
/// <summary>
/// 表名
/// </summary>
public class FildName : TableModel
{
//构造函数
public FildName()
{
this.TableColumns = this.GetColumns(UtilHelper.DB_NAME, "TableName");
}
//私有成员
private int _field1;
//get\set方法以访问和设置私有成员的值
public int replen_drug_id { get => _field1; set => _field1 = value; }
}9. CRUD代码模版
//日期数据赋值
UtilHelper.LocalDateTime().AddHours(8)
//创建人\ 更新人 赋值
UtilHelper.GetUserInfo(HttpContext)
//数据格式转换(主要应用场景 : 字符串转数值型,数值型转字符串)
Convert.Toint32(str1) //字符串转整型
variable.ToSafeString() //数值型转字符串型9.1 增加操作
传入JObject data
设置一个大的try catch
对传入的data进行判空操作
使用QsJsonHelper.JGetJsonAttr() 方法 , 将json数据中的键值取出来 (存入变量中)
对不为null的字段进行格式校验
实例化数据库对象
判断数据库中是否存在要插入的数据
对数据库对象的成员进行赋值操作
使用Add()方法 , 传入主键 , 进行添加操作
使用GetModel()方法 , 获取数据
使用UtilHelper.zhObj() , 传入数据库对象 , 进行json封装
日志记录插入成功 , 返回状态码
/// <summary>
/// XX添加
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
/// <remarks>
/// 请求参数示例:
/// ````````
///{
///"field1": "value1",
///"field2": "value2",
///"field3": "value3",
///"field3": "value4",
///"field4" : "value5"
///
///}
///</remarks>
[HttpPost("apiName")]
public IActionResult AddapiName(JObject data)
{
try
{
//传入数据为空时 , 返回错误状态码
if (data == null)
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("401"));
}
#region 获取json中的属性值
string field1 = QsJsonHelper.JGetJsonAttr(data, "field1");
#endregion
#region 非空格式校验
if (string.IsNullOrEmpty(field1) || string.IsNullOrEmpty(field2))
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("401"));
}
#endregion
//实例化TableName对象
TableName tableName = new TableName();
//判断是否存在具有唯一性的字段值
//若存在脉诊编码或脉诊名称 , 则返回错误状态码
if (baseTcmPulseDiagnosis.Exists($"field1 ='{field1}'"))
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("401"));
}
#region 对tableName的成员进行赋值操作
tableName.field1 = field1;
#endregion
//进行添加操作 , 并判断是否插入成功
int success = baseTcmPulseDiagnosis.Add("pkey");
if (success <= 0)
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("401"));
}
//读取数据
baseTcmPulseDiagnosis.GetModel($"field1 = '{field1}'");
//封装json
JObject res = UtilHelper.zhObj(tableName);
//或自主封装(2选1)
JObject res = new JObject()
{
};
//插入成功 , 记录日志
LogHelper.LogOper("1", "XX", UtilHelper.GetUserInfo(HttpContext), "1", "添加");
//返回插入成功的状态码和json数据
return StatusCode(StatusCodes.Status200OK, UtilHelper.JOutput("201", res));
}
catch (Exception ex)
{
return StatusCode(StatusCodes.Status500InternalServerError, UtilHelper.JOutput("50000001"));
}
}9.2 批量增加
/// <summary>
/// XX批量添加
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
/// <remarks>
/// 请求参数示例:
/// ````````
///{
/// "array": [{
/// "field1":"value1",
/// "field2":"value2",
/// "field3":"value3",
/// "field4":"value4",
/// "field5":"value5"
/// },
/// {
/// "field1":"value1",
/// "field2":"value2",
/// "field3":"value3",
/// "field4":"value4",
/// "field5":"value5"
/// }],
/// "ppzd":["field1","field2"],
/// "nrcz":1
/// }
///</remarks>
[HttpPost("apiNames")]
public IActionResult AddapiNames(JObject item)
{
//获取json的值(array中是所有要插入的数据)
string zybmarray = QsJsonHelper.JGetJsonAttr(item, "array", "[]");
//ppzz(匹配字段) , 值唯一的字段
string ppzd = QsJsonHelper.JGetJsonAttr(item, "ppzd", "[]");
//nrcz是一种处理重复的策略 : 1.覆盖 2.跳过
string nrcz = QsJsonHelper.JGetJsonAttr(item, "nrcz");
//匹配名称
string ppmc = "";
//编号
string bh = "";
//dataArray中包含所有要插的数据值
JArray dataArray = JArray.Parse(zybmarray);
//ppzdArray中包含所有值唯一的字段
JArray ppzdArray = JArray.Parse(ppzd);
if (ppzdArray.Count == 0)
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("401"));
}
//循环匹配字段数组
foreach (var zdobj in ppzdArray)
{
//格式验证
if (zdobj.ToString() != "field1" && zdobj.ToString() != "field2")
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("401"));
}
//赋值
if (zdobj.ToString() == "field1")
{
ppmc = zdobj.ToString();
}
if (zdobj.ToString() == "field2")
{
bh = zdobj.ToString();
}
}
//判空
if (dataArray == null || dataArray.Count == 0)
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("401"));
}
try
{
JArray resArray = new JArray();
//格式校验
foreach (JObject data in dataArray)
{
#region 获取参数
string field1 = QsJsonHelper.JGetJsonAttr(data, "field1");
string field2 = QsJsonHelper.JGetJsonAttr(data, "field2");
#endregion
//格式校验
if (string.IsNullOrEmpty(field1) || string.IsNullOrEmpty(field2))
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("401"));
}
}
//开启事务
using (var scope = new TransactionScope())
{
foreach (JObject data in dataArray)
{
#region 获取json中的属性值
string field1 = QsJsonHelper.JGetJsonAttr(data, "field1");
#endregion
//实例化TableName对象
TableName tableName = new TableName();
string where = "";
//id和名字都一起判断
if (!string.IsNullOrEmpty(ppmc) && !string.IsNullOrEmpty(bh))
{
where = "field1 = " + $"'{field1}'" + " AND " + "field2 = " + $"'{field2}'";
}
//名字判断
else if (!string.IsNullOrEmpty(ppmc) && string.IsNullOrEmpty(bh))
{
where = "field2 = " + $"'{field2}'";
}
//id判断
else if (string.IsNullOrEmpty(ppmc) && !string.IsNullOrEmpty(bh))
{
where = "field1 = " + $"'{field1}'";
}
//判断匹配字段
if (tableName.Exists(where))
{
//判断是否覆盖:1.覆盖。其他跳过
if (nrcz == "1")
{
//添加前判断配覆盖的主键是否已存在
if (string.IsNullOrEmpty(bh))
{
if (tableName.Exists("field1 = " + $"'{field1}'"))
{
scope.Dispose();
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("401"));
}
}
if (string.IsNullOrEmpty(ppmc))
{
if (tableName.Exists("field2 = " + $"'{field2}'"))
{
scope.Dispose();
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("401"));
}
}
tableName.GetModel(where);
#region 赋值
tableName.field1 = field1;
#endregion
//封装json
JObject ress = UtilHelper.zhObj(tableName);
//返回值添加
resArray.Add(ress);
continue;
}
else
{
continue;
}
}
//添加时判断是否存在
if (tableName.Exists("field1 = " + $"'{field1}'"))
{
scope.Dispose();
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("401"));
}
//封装
tableName.field1 = field1;
//封装json
JObject res = UtilHelper.zhObj(tableName);
resArray.Add(res);
}
scope.Complete();
}
//插入成功 , 日志记录并返回状态码
LogHelper.LogOper("1", "XX", UtilHelper.GetUserInfo(HttpContext), "1", "添加");
return StatusCode(StatusCodes.Status200OK, UtilHelper.JOutput("201", resArray));
}
catch (Exception ex)
{
return StatusCode(StatusCodes.Status500InternalServerError, UtilHelper.JOutput("50000001");
}
}9.3 删除操作
传入主键
判断主键是否合法
实例化数据库表对象
查询该条数据是否存在于表中 , 不存在则无法删除
调用DeletePart()方法 , 进行删除
判断是否删除成功 , 若不成功 , 记录删除不成功日志 , 返回错误码
若成功 , 记录删除成功日志 , 返回正确码
/// <summary>
/// XX删除
/// </summary>
/// <param name="field1"></param>
/// <returns></returns>
/// <remarks>
/// 请求参数示例
/// mzbh : 1
/// </remarks>
[HttpDelete("apiName/{field1}")]
public IActionResult DeleteapiName(int field1)
{
try
{
//如果主键编号不合法 , 返回错误状态码
if(field1 <= 0)
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("402"));
}
//实例化TableName对象
TableName tableName = new TableName();
//若查询到该条数据不存在于表中 , 则无法删除 , 返回错误状态码
if (!tableName.Exists($"field1 ='{field1}'"))
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("402"));
}
//删除操作
bool sucess = baseTcmPulseDiagnosis.DeletePart($"field1 ='{field1}'");
//删除不成功 , 日志记录删除失败
if (!sucess)
{
LogHelper.LogOper("3", "XX", UtilHelper.GetUserInfo(HttpContext), "0", "删除");
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("402"));
}
//删除成功 , 日志记录删除成功
LogHelper.LogOper("3", "XX", UtilHelper.GetUserInfo(HttpContext), "1", "删除");
return StatusCode(StatusCodes.Status200OK, UtilHelper.JOutput("202"));
}
catch (Exception ex)
{
return StatusCode(StatusCodes.Status500InternalServerError, UtilHelper.JOutput("50000001"));
}
}9.4 批量删除
/// <summary>
/// XX批量删除
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
/// <remarks>
/// 请求参数示例:
/// ```
/// {
/// "ids": "['1','2']"
/// }
/// </remarks>
[HttpDelete("apiName")]
public IActionResult DeleteapiName(JObject data)
{
try
{
//数据为空 , 返回错误状态码
if (data == null)
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("402"));
}
//json放到JArray数组中
JArray ids = JArray.Parse(data["ids"].ToString() == null ? "[]" : data["ids"].ToString());
//格式判断
if (ids.Count == 0)
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("402"));
}
//实例化TableName对象
TableName tableName = new TableName();
//拼接sql
StringBuilder str = new StringBuilder();
str.Append($"pkey in (");
foreach (int obj in ids)
{
str.Append($"{obj},");
}
str.Append(")");
str.Remove(str.Length - 2, 1);
//删除加判断
if (tableName.DeletePart(str.ToString()))
{
LogHelper.LogOper("3", "XX", UtilHelper.GetUserInfo(HttpContext), "1", "删除");
return StatusCode(StatusCodes.Status200OK, UtilHelper.JOutput("202"));
}
else
{
LogHelper.LogOper("3", "XX", UtilHelper.GetUserInfo(HttpContext), "0", "删除");
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("402"));
}
}
catch (Exception ex)
{
return StatusCode(StatusCodes.Status500InternalServerError, UtilHelper.JOutput("50000001");
}
}9.5 修改操作
传入JObject data , 传入主键
判断data是否为null 或 要修改的逐渐编号是否合法
获取json中的属性值
格式校验
实例化数据库表对象
判断是否存在传入的主键编号
调用GetModel()方法获取数据
对数据库表对象的成员进行赋值
调用Update()方法进行修改操作
若不成功 , 则记录失败日志 , 返回错误状态码
使用UtilHelper.zhObj() , 传入数据库对象 , 进行json封装
日志记录插入成功 , 返回状态码
/// <summary>
/// XX修改
/// </summary>
/// <param name="data"></param>
/// <param name="pkey"></param>
/// <returns></returns>
/// <remarks>
/// 请求参数示例:
/// ```
/// pkey : 1
/// change :
///{
///"field1": "value1",
///"field2": "value2",
///"field3": "value3",
///"field4": "value4",
///
///}
/// </remarks>
[HttpPut("apiName/{pkey}")]
public IActionResult PutapiName(JObject data, int pkey)
{
try
{
//若传入的修改数据为null 或要修改的编号不合法 , 直接返回错误状态码
if(data == null || pkey <= 0)
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("403"));
}
#region 获取json中的属性值
string field1 = QsJsonHelper.JGetJsonAttr(data, "field1");
#endregion
//格式校验
if (string.IsNullOrEmpty(field1) || string.IsNullOrEmpty(field2))
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("403"));
}
//实例化TableName对象
TableName tableName = new TableName();
//若不存在要修改的脉诊编号 , 则返回错误状态码
if (!tableName.Exists($"pkey ='{pkey}'"))
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("403"));
}
//拿到数据
tableName.GetModel($"pkey ='{pkey}'");
#region 赋值
tableName.field1 = field1;
#endregion
//修改操作
bool success = tableName.Update("pkey");
//不成功 , 记录不成功的日志
if (!success)
{
LogHelper.LogOper("2", "XX", UtilHelper.GetUserInfo(HttpContext), "0", "修改");
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("403"));
}
//封装为json
JObject res = UtilHelper.zhObj(tableName);
//成功
LogHelper.LogOper("2", "XX", UtilHelper.GetUserInfo(HttpContext), "1", "修改");
return StatusCode(StatusCodes.Status200OK, UtilHelper.JOutput("203", res));
}
catch (Exception ex )
{
return StatusCode(StatusCodes.Status500InternalServerError, UtilHelper.JOutput("50000001"));
}
}9.6 查看操作
传入主键的值
判断主键值是否合法
实例化数据库表对象
查看表中是否有该条数据 , 不存在则返回状态码
调用GetModel()方法 , 获取值
封装json
返回状态码和查看结果
/// <summary>
/// XX单个查看
/// </summary>
/// <param name="pkey"></param>
/// <returns></returns>
/// <remarks>
/// 1
/// </remarks>
[HttpGet("apiName/{pkey}")]
public IActionResult GetapiName(int pkey)
{
try
{
if(pkey <= 0)
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("404"));
}
//实例化TableName对象
TableName tableName = new TableName();
//不存在 , 返回错误状态码
if (!tableName.Exists($"pkey ='{pkey}'"))
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("404"));
}
//获取值
tableName.GetModel($"pkey ='{pkey}'");
//封装为json
JObject res = new JObject()
{
["fields1"] = tableName.fields1,
["fields2"] = tableName.fields2.ToString("yyyy-MM-dd HH:mm:ss")//fields2为日期类型
};
return StatusCode(StatusCodes.Status200OK, UtilHelper.JOutput("204", res));
}
catch (Exception ex)
{
return StatusCode(StatusCodes.Status500InternalServerError, UtilHelper.JOutput("50000001"));
}
}9.7 批量查看
/// <summary>
/// XX批量查看
/// </summary>
/// <param name="limit">指定返回记录的数量</param>
/// <param name="page">指定返回记录的开始位置</param>
/// <param name="per_page">指定每页记录数</param>
/// <param name="sortby">指定排序字段</param>
/// <param name="order">指定排序方式,asc:正序,desc:倒序</param>
/// <param name="column">指定查询列,逗号隔开</param>
/// <param name="search_value">指定模糊查询的内容</param>
/// <param name="search_column">指定搜索列,逗号隔开</param>
/// <param name="filter">指定过滤字段,格式为[{"column":"inte_system_tag","value":"1"}]</param>
/// <param name="time">指定时间筛选的内容,格式为[{"column":"sur_start_time","start":"2020-12-22T23:15:00","end":"2022-12-22T23:20:00"}]</param>
/// <returns></returns>
/// <remarks>
///
/// </remarks>
[HttpGet("apiName")]
public IActionResult apiName(int? limit = 0, int? page = 1, int? per_page = 10, string? sortby = "gxsj", string? order = "desc", string? column = "", string? search_column = "", string? search_value = "", string? filter = "[]", string? time = "[]")
{
try
{
//实例化TableName对象
TableName tableName = new TableName();
//调用sql拼接
JObject sqlObj = ControllerHelper.ConcatSql(limit, page, per_page, sortby, order, column, search_column, search_value, filter, time);
JArray jArray = baseTcmPulseDiagnosis.JDataTableToList(baseTcmPulseDiagnosis.GetList(column.Replace(",", ","), sqlObj["where"].ToString(), sqlObj["limit"].ToString(), sqlObj["order"].ToString()).Tables[0]);
//封装json
JObject res = new JObject()
{
["list"] = jArray,
["total"] = baseTcmPulseDiagnosis.GetTotal(sqlObj["where"].ToString()),
};
return StatusCode(StatusCodes.Status200OK, UtilHelper.JOutput("201", res));
}
catch (Exception ex)
{
return StatusCode(StatusCodes.Status400BadRequest, UtilHelper.JOutput("50000001");
}
}10. gitee使用
10.1 下载
git下载 : https://git-scm.com/
gui小乌龟(可选软件) : https://tortoisegit.org/download/
10.2 配置
配置RSA公钥
打开git bash , 一直回车 , 公钥文件会存在 c/user/用户名称/.ssh/id_rsa.pub中
ssh-keygen -t rsa -C "你的邮箱"密钥全部复制到gitee网站中
官网---个人---设置---ssh公钥---下面的公钥文本域
进行基础信息配置
打开git bash , 输入以下信息
git config --global user.name "你的名字或昵称" //注意名字一定是网站上@后边的内容 git config --global user.email "你的邮箱"
10.3 命令
git pull origin master
10.4 上传修改后的文件流程(git)
在修改的文件目录下 , 右键点击 open git bash here
git add XX.cs
git commit - m "注释"
git pull origin master
git push origin master
若出现此问题 , 先pull 再push

10.5 上传修改后的文件流程(可视化)
右键 -> Git 提交(c) ->master
点击提交 -> 推送
若有冲突 , 先拉取 解决冲突 ,再推送
若报错:
git pull报错:error: Your local changes to the following files would be overwritten by merge
方法1:
保留刚才本地修改的代码,并把git服务器上的代码pull到本地(本地刚才修改的代码将会被暂时封存起来)
git stash
git pull origin master
git stash pop如此一来,服务器上的代码更新到了本地,而且你本地修改的代码也没有被覆盖,之后使用add,commit,push 命令即可更新本地代码到服务器了。
方法2:
完全地覆盖本地的代码,只保留服务器端代码,则直接回退到上一个版本,再进行pull:
git reset --hard
git pull origin master11 . 技术
11.1 JWT
11.2 RDBC
11.3 消息推送
1. 数据库设计
准备发送的消息(ExtrMsg表)
数据样例
日志信息(ExtrMsgLog表)
2.代码思想
读取 ExtrMsg 表 , 找到待发送且未被删除的所有消息 (以JArray来存储)
foreach循环遍历JArray数组(即每一遍循环 , 处理一条消息)
获取一条消息中的所有字段值 , 对 msg_type 字段值进行判断处理(短信发送和邮箱发送两种情况)
要做好对 ExtrMsgLog 表的处理 , 发送成功与否 , 都需要进行记录
11.4 华为云API
1.认证鉴权 (https://support.huaweicloud.com/intl/zh-cn/api-workspace/workspace_09_0010.html)
Token认证:通过Token认证调用请求。
AK/SK认证:通过AK(Access Key ID)/SK(Secret Access Key)加密调用请求。

参与讨论
(Participate in the discussion)
参与讨论