RsCode
中对数据库的操作,使用FreeSql
,支持国产,并使用它做了一些封装,包括:多数据库管理,分页查询,UnitOfWork
扩展等
配置数据库
1.1 appsettings.json中,配置数据库连接
json
{
//数据库连接
"ConnectionStrings": {
"DefaultConnection": "Server=127.0.0.1;Uid=root;Pwd=123456;Database=test;Port=3306;",
"DefaultConnection2": "Data Source=rscode.db;"
}
}
1.2 添加数据库服务
csharp
builder.Services.AddDatabase(FreeSql.DataType.MySql, "DefaultConnection");
builder.Services.AddDatabase(FreeSql.DataType.Sqlite, "DefaultConnection2");
1.3 添加数据库提供程序
需要访问什么数据库,就安装对应的 FreeSql.Provider.XX
,也可直接安装 FreeSql.All
Package Name | 说明 |
---|---|
FreeSql.Provider.MySql | 基于 MySql.Data(Oracle 官方) |
FreeSql.Provider.MySqlConnector | 基于 MySqlConnector(开源社区,推荐++) MySQL, MariaDB, Percona, Amazon Aurora, Azure Database for MySQL, Google Cloud SQL for MySQL, OceanBase, Doris, Tidb 等等 |
FreeSql.Provider.PostgreSQL | 基于 PostgreSQL 9.5+ |
FreeSql.Provider.SqlServer | 基于 SqlServer 2005+ |
FreeSql.Provider.SqlServerForSystem | 基于 System.Data.SqlClient + SqlServer 2005+ |
FreeSql.Provider.Sqlite | 基于 System.Data.SQLite.Core |
FreeSql.Provider.SqliteCore | 基于 Microsoft.Data.Sqlite.Core,需安装 bundle_xxx |
FreeSql.Provider.Duckdb | 基于 DuckDB.NET.Data.Full |
FreeSql.Provider.ClickHouse | 基于 ClickHouse.Client |
FreeSql.Provider.QuestDb | 基于 Npgsql 和 RestApi |
FreeSql.Provider.Oracle | |
FreeSql.Provider.OracleOledb | 基于 Oledb 解决 US7ASCII 中文乱码问题 |
FreeSql.Provider.Firebird | |
FreeSql.Provider.MsAccess | |
FreeSql.Provider.Dameng | 基于 达梦数据库 |
FreeSql.Provider.ShenTong | 基于 神舟通用数据库 |
FreeSql.Provider.KingbaseES | 基于 人大金仓数据库 |
FreeSql.Provider.GBase | 基于 南大通用GBase数据库 |
FreeSql.Provider.Xugu | 基于 虚谷数据库 |
FreeSql.Provider.Odbc | 基于 ODBC |
FreeSql.Provider.Custom | 自定义适配 SqlServer2000, PolarDB, KunDB, 其它国产数据库 等等 |
操作数据库
2.1使用IApplicationDbContext访问数据
在构造中注入IApplicationDbContext
IApplicationDbContext.Current
代表当前使用的数据库,默认值是DefaultConnection
IApplicationDbContext.ChangeDatabase("dbConnStr")
方法可以更换当前使用的数据库
实例代码:
csharp
//注入IApplicationDbContext实例
IApplicationDbContext dbContext;
//略
//当前数据库连接
dbContext.Current;
//更换数据库
dbContext.ChangeDatabase(connName="DefaultConnection");
//create unitofwork
dbContext.CreateUnitOfWork();
//获取Repository
dbContext.GetRepository<TEntity>();
dbContext.GetRepository<TEntity,TKey>();
2.2 实体特性
csharp
[Table(Name ="rswl_user_info")]
public class UserModel
{
[Column(IsPrimary =true)]
//[Column(IsIdentity =true)]//自增长的主键
public string UserId { get; set; }
[Column(DbType="text")]
public string UserName { get; set; }
//导航属性 用户相关文章
[Navigate(nameof(User.ArticleId))]
public List<Article> Articles { get; set; }
[Column(IsIgnore=true)] //是否不映射
[Column(IsNullable = false)] //手动设置是否为空
public string age{get;set;}
//乐观锁的原理,是利用实体某字段,如:long version,更新前先查询数据,此时 version 为 1,更新时产生的 SQL 会附加 where version = 1,当修改失败时(即 Affrows == 0)抛出异常(DbUpdateVersionException)。
//每个实体只支持一个乐观锁属性,支持 int/long/string/Guid
//适用 SetSource 更新数据,无论使用什么方法更新 version 的值都会增加 1
[Column(IsVersion = true)]
public int Version { get; set; }
}
2.3 常用sql操作
csharp
public class Demo
{
IFreeSql db;
public void Demo(IApplicationDbContext dbContext)
{
db=dbContext.Current;
}
public async Task Test()
{
await db.Select<UserModel>().FirstAsync();
//OneToOne、ManyToOne
db.Select<Tag>().Where(a => a.Parent.Parent.Name == "English").ToList();
//OneToMany
db.Select<Tag>().IncludeMany(a => a.Tags, then => then.Where(sub => sub.Name == "foo")).ToList();
//ManyToMany
db.Select<Song>()
.IncludeMany(a => a.Tags, then => then.Where(sub => sub.Name == "foo"))
.Where(s => s.Tags.Any(t => t.Name == "Chinese"))
.ToList();
//Other
db.Select<YourType>()
.Where(a => a.IsDelete == 0)
.WhereIf(keyword != null, a => a.UserName.Contains(keyword))
.WhereIf(role_id > 0, a => a.RoleId == role_id)
.Where(a => a.Nodes.Any(t => t.Parent.Id == t.UserId))
.Count(out var total)
.Page(page, size)
.OrderByDescending(a => a.Id)
.ToList();
}
}
csharp
//OneToOne、ManyToOne
db.Select<Tag>().Where(a => a.Parent.Parent.Name == "English").ToList();
//OneToMany
db.Select<Tag>().IncludeMany(a => a.Tags, then => then.Where(sub => sub.Name == "foo")).ToList();
//ManyToMany
db.Select<Song>()
.IncludeMany(a => a.Tags, then => then.Where(sub => sub.Name == "foo"))
.Where(s => s.Tags.Any(t => t.Name == "Chinese"))
.ToList();
//Other
db.Select<YourType>()
.Where(a => a.IsDelete == 0)
.WhereIf(keyword != null, a => a.UserName.Contains(keyword))
.WhereIf(role_id > 0, a => a.RoleId == role_id)
.Where(a => a.Nodes.Any(t => t.Parent.Id == t.UserId))
.Count(out var total)
.Page(page, size)
.OrderByDescending(a => a.Id)
.ToList();
未设置导航属性关系的,临时指定关系(只支持一对多):
csharp
db.Select<Goods>().IncludeMany(a => a.Comment.Where(b => b.TagId == a.Id));
只查询每项子集合的前几条数据,避免像 EfCore 加载所有数据导致 IO 性能低下(比如某商品下有 2000 条评论):
csharp
db.Select<Goods>().IncludeMany(a => a.Comment.Take(10));
更多操作查看freesql文档
2.4仓储模式
RsCode自定义封装了一些数据库常用操作,使用FreeSql
做为orm
开启UnitOfWork服务
csharp
//必要步骤:添加动态代理
builder.Host.UseServiceProviderFactory(new DynamicProxyServiceProviderFactory());
builder.Services.AddDatabase(FreeSql.DataType.MySql, "DefaultConnection");
builder.Services.AddUnitOfWork();
定义UserInfo实体类
csharp
[TableName("rswl_user_info")]
public partial class UserModel
{
[Column(Identity=true)]
public long Id { get; set; }
public string UserName { get; set; }
}
实现Repository
csharp
public interface IUserRepository
{
}
public class UserRepository:IUserRepository
{
IRepository<UserModel> repository;
public UserRepository(IRepository<UserModel> repository)
{
this.repository=repository;
}
[]
public async Task<UserModel> CreateAndGetUserByRepository(string name)
{
repository.Insert(new UserModel()
{
UserId=Guid.NewGuid().ToString("N"),
UserName=name
});
return await repository.Select.Where(x => x.UserName == name).FirstAsync();
}
public async Task<PageData<UserModel>> PageInfoAsync(int page,int pageSize)
{
//分页查询
ISelect<UserModel> select=repository.Page(1,10).Where(x=>x.UserId=="xxx");
return await repository.PageAsync(page,pageSize,select);
}
}
//或者
public interface IUserRepository:IRepository<UserModel>
{}
public class UserRepository:Repository<UserModel>,IUserRepository
{
public UserRepository(IApplicationDbContext applicationDbContext):base(applicationDbContext){}
//其它资源可通过属性注入
[FromServiceContext]
public IRepository<UserExtInfo> userExtRepository { get; set; }
}