C# 动态创建类,动态创建表,支持多库的数据库维护方案
1、创建表
SqlSugar支持了3种模式的建表,非常的灵活,可以MYSQL MSSQL ORACLE等用同一语法创建数据库,不需要考虑数据库的兼容性
中间标准:
string 大文本 |
5.1.3.44-preview06 推荐 [SugarColumn(ColumnDataType = StaticConfig.CodeFirst_BigString)] |
string 设置长度的字符串 |
[SugarColumn(Length=10)] public string FieldName{ get; set; } |
int 整数 |
public int FieldName{ get; set; } |
short 整数小 |
public short FieldName{ get; set; } |
long 大数字 |
public long FieldName{ get; set; } |
bool 真假 |
public bool FieldName{ get; set; } |
decimal 默认 |
public decimal FieldName{ get; set; } |
decimal 自定义 |
//18,2 18,4 18,6 这几种兼容性好 [SugarColumn(Length=18,DecimalDigits=2)] public decimal FieldName{ get; set; } |
DateTime 时间 |
public DateTime FieldName{ get; set; } |
枚举 (数据库存int) |
public 枚举 FieldName{ get; set; } |
byte[] 二进制 |
public byte[] FileInfo{get;set;} 建议:升级到 SqlSugarCore 5.1.3.46-preview09 及以上 对多库支持了比较好 |
SqlServer特殊配置:和他库不同一般选用Nvarchar,可以使用这个配置让他和其他数据库区分(其他库是varchar) |
DbType = SqlSugar.DbType.SqlServer, ConnectionString ="字符串", IsAutoCloseConnection = true ,
} |
1.1通过特性建表
我们可以通过创建关体来进行建表
public class CodeFirstTable1
{
[SugarColumn(IsIdentity = true, IsPrimaryKey = true)]
public int Id { get; set; }
public string Name { get; set; }
//ColumnDataType 自定格式的情况 length不要设置 (想要多库兼容看4.2和9)
[SugarColumn(ColumnDataType = "Nvarchar(255)")]
public string Text { get; set; }
[SugarColumn(IsNullable = true)]//可以为NULL
public DateTime CreateTime { get; set; }
} /***创建单个表***/
db.CodeFirst.SetStringDefaultLength(200).InitTables(typeof(CodeFirstTable1));//这样一个表就能成功创建了
/***手动建多个表***/
db.CodeFirst.SetStringDefaultLength(200)
.InitTables(typeof(CodeFirstTable1),typeof(CodeFirstTable2));
建表特性如下
名称 | 描述 |
---|---|
IsIdentity | 是否创建自增标识 |
IsPrimaryKey | 是否创建主键标识 |
ColumnName | 创建数据库字段的名称(默认取实体类属性名称) |
ColumnDataType |
创建数据库字段的类型 用法1: “varchar(20)” 不需要设置长度 用法2: 不设置该参数 系统会根据C#类型自动生成相应的数据库类型 用法3: 多库兼容可以用 :看标题9 |
IsIgnore | ORM不处理该列 |
ColumnDescription | 备注 表注释 (新版本支持XML文件) |
Length | 长度 设成10会生成 xxx类型(10), 没括号的不设置 |
IsNullable | 是否可以为null默为false |
DecimalDigits | 精度 如 decimal(18,2) length=18,DecimalDigits=2 |
OracleSequenceName | 设置Oracle序列,设置后该列等同于自增列 |
OldColumnName | 修改列名用,这样不会新增或者删除列 |
IndexGroupNameList | 已弃用 ,新用法看文档4.3 |
UniqueGroupNameList | 已弃用, 新用法看文档4.3 |
注意:有2个属性用处不同 DefaultValue IsOnlyIgnoreInsert |
DefaultValue=默认值 用来建表设置字段默认值 IsOnlyIgnoreInsert=true 插入数据时取默认值 很多情况需要2个一起使用 如果只建表不插入数据用1个 如果建表并且插入数据用2个 |
2.2无特性建表
如果我们的实体不需要加特性,那么我们可以通过特性方式建表
SugarClient db = new SqlSugarClient(new ConnectionConfig()
{
DbType = DbType.SqlServer,
ConnectionString = Config.ConnectionString3,
InitKeyType = InitKeyType.Attribute,
IsAutoCloseConnection = true,
ConfigureExternalServices = new ConfigureExternalServices()
{
EntityService = (s, p) =>
{
//如果是Order实体进行相关配置
p.IfTable<Order>()
.UpdateProperty(it => it.id, it =>
{
it.IsIdentity = true;
it.IsPrimarykey = true;
})
.UpdateProperty(it => it.Name, it => {
it.Length = 100;
it.IsNullable = true; })
.OneToOne(it => it.Item, nameof(Order.ItemId)); //如果Custom实体进行相关配置
p.IfTable<Custom>()
.UpdateProperty(it => it.id, it =>
{
it.IsIdentity = true;
it.IsPrimarykey = true;
})
.UpdateProperty(it => it.Text, it => {
it.DataType= StaticConfig.CodeFirst_BigString;//支持多库的MaxString用法
}) //可以结合全局逻辑一起使用,下面的和上面的有冲突的话,下面会覆盖上面的 //统一设置 nullable等于isnullable=true
//低版本C#看标题2.2
if(p.IsPrimaryKey==false&&new NullabilityInfoContext()
.Create(c).WriteState is NullabilityState.Nullable)
{
p.IsNullable = true;
} }
}
});
//性能说明:
//EntityService 相同实体只会执行一次性不需太操作
1.3 无实体建表
功能与实体建类一模一样,如果使用SqlSugar中间标准可以支持多个数据库一套代码建表
var type = db.DynamicBuilder().CreateClass("UnitEntityA",
new SugarTable()
{
TableDescription = "表备注",
//DisabledUpdateAll=true 可以禁止更新只创建
}
)
.CreateProperty("Id", typeof(int), new SugarColumn() { IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "列备注" })
.CreateProperty("Name", typeof(string), new SugarColumn() {Length=200, ColumnDescription = "列备注" })
.BuilderType(); db.CodeFirst.InitTables(type);
3、数据库维护
SqlSugar有一套数据库维护API,并且能够很好的支持多种数据库,例如备份数据库等常用功能
//例1 获取所有表
var tables = db.DbMaintenance.GetTableInfoList(false);//true 走缓存 false不走缓存
foreach (var table in tables)
{
Console.WriteLine(table.Description);//输出表信息 //获取列信息
//var columns=db.DbMaintenance.GetColumnInfosByTableName("表名",false);
} //例2
db.DbMaintenance.IsAnyTable("tablename",false)//验证表名是否缓存不走缓存
所以API
GetDataBaseList | 获取所有数据库名称 | List |
GetViewInfoList | 查询所有视图 | List |
GetTableInfoList | 获取所有表,查询所有的表 (GetTableInfoList(是否缓存)) | List |
GetColumnInfosByTableName |
获取列根据表名,获取字段,字段信 息GetColumnInfosByTableName(表名,是否缓存) |
List |
GetIsIdentities | 获取自增列 | List |
GetPrimaries | 获取主键 | List |
IsAnyTable | 表是否存在,判断表存不存在 ( IsAny(表名,是否缓存)) | bool |
IsAnyColumn | 列是否存在 | bool |
IsPrimaryKey | 主键是否存在 | bool |
IsIdentity | 自增是否存在 | bool |
IsAnyConstraint | 约束是否存在 | bool |
DropTable | 删除表 | bool |
TruncateTable | 清空表 | bool |
CreateTable |
看标题 1.1,1.2,1.3 |
bool |
AddColumn | 添加列 | bool |
UpdateColumn | 更新列 | bool |
AddPrimaryKey | 添加主键 | bool |
DropConstraint | 删除约束 | bool |
BackupDataBase | 备份库 | bool |
DropColumn | 删除列 | bool |
RenameColumn | 重命名列 | bool |
AddDefaultValue | 添加默认值 | bool |
AddTableRemark | 添加表描述,表注释 | bool |
AddColumnRemark | 添加列描述,表注释 | bool |
DeleteColumnRemark | 删除列描述,表注释 | bool |
RenameTable | 重命名表 | bool |
CreateIndex | 创建索引,唯一约束(唯一索引) | bool |
IsAnyIndex | 索引是否存在 | bool |
GetIndexList | 获取所有索引 | |
GetProcList | 获取所有存储过程 |
2、跨库支持
可以自动识别在哪个库
实体
[TenantAttribute("1")]//对应ConfigId
public class C1Table
{
public string Id { get; set; }
} [TenantAttribute("2")]
public class C2Table
{
public string Id { get; set; }
}
查询
//通过ConfigId进行数据库区分
var db = new SqlSugarClient(new List<ConnectionConfig>()
{
//这儿声名所有上下文都生效
new ConnectionConfig(){ConfigId="0",DbType=DbType.SqlServer,ConnectionString=..,IsAutoCloseConnection=true},
new ConnectionConfig(){ConfigId="1",DbType=DbType.MySql,ConnectionString=..,IsAutoCloseConnection=true }
});
//自动跨库联表查询
var query5 = db.QueryableWithAttr<Order>()//如果MySql和SqlServer自动支持同服务器的跨库联表查询
.LeftJoin<Custom> ((o, cus ) => o.CustomId == cus.Id)//多个条件用&&
.LeftJoin<OrderDetail> ((o, cus, oritem) => o.Id == oritem.OrderId)
.Where(o => o.Id == 1)
.Select((o, cus , oritem) => new ViewOrder { Id = o.Id, CustomName = cus.Name })
.ToList();
//手动跨库联表查询 ,这种方式结合dblink可以跨服务器
var query5 = db.Queryable().As("xxx.表名")
.LeftJoin<Custom> ((o, cus ) => o.CustomId == cus.Id ,"yyyy.表名")
.LeftJoin<OrderDetail> ((o, cus, oritem) => o.Id == oritem.OrderId ,"zzzz.名表")
.Where(o => o.Id == 1)
.Select((o, cus , oritem) => new ViewOrder { Id = o.Id, CustomName = cus.Name })
.ToList();
插入
db.InsertableWithAttr(list).Execommand()
更新
db.UpdateableWithAttr(list).Execommand()
删除
db.UpdateableWithAttr(list).Execommand()
只要实体配置了数据库,就不要考虑换库了,直接使用,并且支持事务
3、过滤器
SqlSugar支持了全新的过滤器,可以是接口,集成该接口的类都生效,支持多表查询
db.QueryFilter
.AddTableFilter<IDeletedFilter>(it => it.IsDeleted==false)//IDeletedFilter是自定义接口,继承这个接口的实体有效
.AddTableFilterIF<ITenantFilter>(isAdmint==false,it=>it.OrgId==用户OrgId);//ITenantFilter自定义接口 //用例1:单条语句清空,只影响当前语句
db.Queryable<Order>().ClearFilter().ToList();//所有过滤器都无效
db.Queryable<Order>().ClearFilter<IDeletedFilter>().ToList();//只有IDeletedFilter过滤器无效
db.Queryable<Order>().ClearFilter<IDeletedFilter,ITenantFilter>().ToList();//IDeletedFilter+ITenantFilter无效 //用例2:当前上下文清空 ,不会影响其他请求,只是当前请求清空
db.QueryFilter.Clear();
db.QueryFilter.Clear<IDeletedFilter>(); //用例3:清空并还原 ,不会影响其他请求,只是当前请求清空
db.QueryFilter.ClearAndBackup();//有多个重载 ClearAndBackup<T,T2>();
db.Queryable<Order>().ToList();
db.QueryFilter.Restore();//还原过滤器 (适合下面代码还需要过滤器情况)
4、子查询升级
1. ToList() 可以直接查询一个对象
2. First() 可以直接查单个对象
3.ToList(it=>it.Id) 可以查List<int>一个字段集合
4..SelectStringJoin(z => z.Name, ",") 子查询将一列用逗号拼接成字符串
var list=db.Queryable<Order>()
.Select(it => new
{
CustomId = it.CustomId,
OrderId = it.Id,
OrderName = it.Name,
CustomList = SqlFunc.Subqueryable<Custom>().Where(c => c.Id == it.CustomId).ToList()
})
.ToList();
5、自定义类型支持
5.1 自定义类型转换器
下面只是讲解怎么定义转换器,ORM自带的功能就包含下面功能,只是用来讲解
public class DictionaryConvert : ISugarDataConverter
{
public SugarParameter ParameterConverter<T>(object value, int i)
{
//该功能ORM自带的IsJson就能实现这里只是用这个用例来给大家学习
var name = "@myp" + i;
var str = new SerializeService().SerializeObject(value);
return new SugarParameter(name, str);
} public T QueryConverter<T>(IDataRecord dr, int i)
{
//打断点调试
//该功能ORM自带的IsJson就能实现这里只是用这个用例来给大家学习
var str = dr.GetValue(i) + "";
return new SerializeService().DeserializeObject<T>(str);
}
}
//使用自定义转换器
[SugarColumn(ColumnDataType="varchar(2000)",SqlParameterDbType=typeof(DictionaryConvert))]
public Dictionary<string, object> DcValue { get; set; }//5.1.3.53-preview08
现有类型支持
5.1 json类型
https://www.donet5.com/Home/Doc?typeId=1232
5.2 枚举类型
int存储:直接用就行了
public DbType DcValue { get; set; }
string存储:高版本如下写法
[SugarColumn(ColumnDataType="varchar(20)",SqlParameterDbType=typeof(EnumToStringConvert))]
public DbType DcValue { get; set; }
3.数据库独有类型支持
看左边菜单 【数据库特性】 该菜单下面有 SqlServer菜单或者MySql菜单等 , 针对不同数据库都有专门的介绍
总结
SqlSugar在2021年到2022年大量的开源应用使用了SqlSugar,带动了SqlSugar的快速发展,我这边要感谢大家
Admin.NET通用管理平台
ZrAdminNetCore 后台
管理Yi框架(Ruoyi Vue)
SimpleAdmin (new)
vboot-netmagic.net (Vue2.0)
网关采集系统(Blazor)
RuYiAdmin
CoreShop商城
Blog.Core
YuebonCore
企业级框架Furion
WebFirst腾讯
APIJSON.NETWaterCloud微服务
ViperFamilyBucket应用框架通用后台
SmartSqlWMS仓库管理系统a
pevolo-apiFytSoaCms
喜欢SqlSugar的可以在下面源码点个赞,点个关注
源码: https://github.com/DotNetNext/SqlSugar/
C# 动态创建类,动态创建表,支持多库的数据库维护方案的更多相关文章
- 解决linux 乌班图下使用eclipse创建类和其他各种操作进程卡死的问题的一种可能方法
[转载]http://blog.csdn.net/u010652906/article/details/51626257Eclipse设置面板菜单可以点,左边面板不出现,创建类.创建包都会卡死的问题, ...
- vc++基础班[28]---动态数组及动态链表的讲解
C++中也有相应的动态数组.动态链表.映射表的模板类,就是STL中的:vector.list.map 他们属于C++标准中的一部分,对于程序的移植性来说也是不错的,但是在MFC编程中使用 CArray ...
- Hive 根据表中某个字段动态分区 以及临时表创建
使用hive储存数据时,需要对做分区,如果从kafka接收数据,将每天的数据保存一个分区(按天分区),保存分区时需要根据某个字段做动态分区,而不是傻傻的将数据写到某一个临时目录最后倒入到某一个分区,这 ...
- OC 反射-->动态创建类
系统方法 NSLog(@"%s", __func__); //打印出类的方法名称,如: //打印结果:2018-02-22 10:52:15.394575+0800 DemoRun ...
- type动态创建类
在一些特定场合,需要动态创建类,比如创建表单,就会用到type动态创建类,举个例子: class Person(object): def __init__(self,name,age): self.n ...
- Python面试常用的高级用法,怎么动态创建类?
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Python专题的第16篇文章,今天我们来聊聊Python当中的元类. 元类是Python当中的高级用法,如果你之前从来没见过这个术语 ...
- 自己动手之使用反射和泛型,动态读取XML创建类实例并赋值
前言: 最近小匹夫参与的游戏项目到了需要读取数据的阶段了,那么觉得自己业余时间也该实践下数据相关的内容.那么从哪入手呢?因为用的是Unity3d的游戏引擎,思来想去就选择了C#读取XML文件这个小功能 ...
- ios动态创建类Class
[Objective-C Runtime动态加载]---动态创建类Class 动态创建类Class,动态添加Class成员变量与成员函数,动态变量赋值与取值,动态函数调用等方法 a.使用objc_al ...
- python动态创建类的声明
动态创建类的声明 使用内置函数type,原型:class type(name, bases, dict)name是类的名字,相当于__class__bases是类的基类,元组,可以有多个基类,但是基类 ...
- C#动态创建和动态使用程序集、类、方法、字段等
C#动态创建和动态使用程序集.类.方法.字段等 分类:技术交流 (3204) (3) 首先需要知道动态创建这些类型是使用的一些什么技术呢?其实只要相关动态加载程序集呀,类呀,都是使用反射,那么动 ...
随机推荐
- 简单的理解synchronized锁升级
前言 今天碰到一个synchronized锁升级的问题, 查了查, 发现一个帖子举例说明比较贴切, 特此转发, 如有问题, 欢迎讨论说明 转自: 木叶盒子 https://www.bilibili.c ...
- OpenEuler 中C与汇编的混合编程
2.5.1用汇编代码编程 将C代码编译成汇编代码 C代码: /**********a.c file********/ #include <stdio.h> extern int B(); ...
- Delphi中纤程的使用
首先我们来看看纤程的定义 纤程(来自百科): 纤程是Windows为了将Unix服务程序更好的移植到Windows上而创建的, 线程是在Windows内核中实现的,纤程是在用户模式下实现的,内核对纤程 ...
- 给定两个字符串,均只包含英文字母,需区分大小写,一个是源字符串SS(长度<1000), 另一个是目标字符串TS(长度<1000),请问能否通过删除SS中的字符(不改变顺序)将它变换成TS,如果可以输出“YES",不可以则输出“NO"。 输入说明:第一行为源字符串SS,第二行为目标字符串TS。
import java.util.Scanner;/* 给定两个字符串,均只包含英文字母,需区分大小写,一个是源字符串SS(长度<1000), 另一个是目标字符串TS(长度<1 ...
- 比较有趣的C语言小程序
1.判断是否是闰年: #include <stdio.h> int main(void) { int year, a; printf("Please enter ...
- Surface Pro (1796),安装Win11之后出现的问题。
2020年年中我为了体验微软新的操作系统,加入了Review计划,即:Windows预览体验计划.然后升级到了Win11.由于苏菲一直是作为辅助设备用,所以平时就是开节电模式,中途也升级了几次Win1 ...
- CEOI 2021
CEOI 2021 \(pts\):64 + 0 + 4 \(T1 : 64pts\) 首先我们肯定知道对于相同的数,一定是放在一起才是最优的,随意我们对于每段查询的区间要保证有序,然后我们发现,每个 ...
- C#——》Web Api 操作MySQL数据库公共类:MySql.Data
使用MySql.Data 连接mysql 数据库,需先引用MySql.Data ,用过MySql.Data.dll操作Mysql数据库. 1,在工具-Nuget包管理器-管理解决方案的Nuget程序包 ...
- Python 错误:TypeError: range() takes no keyword arguments
问题描述: for循环时使用range()出错: for page in range(start=1, stop=8 + 1,step=1): print(page) 结果报错TypeError: r ...
- centos7 系统运行中做raid磁盘阵列
插入磁盘 lsblk查看磁盘总体情况 对sdb1等需要做的硬盘进行制作 fdisk /dev/sdb 开始 n 创建 p 给资源回车 重选代码 t 确认磁盘阵列代码 fd 保存w 首先安装工具 mda ...