├── .gitattributes ├── src ├── .vs │ └── Sodao.Core │ │ └── v15 │ │ └── Server │ │ └── sqlite3 │ │ ├── db.lock │ │ └── storage.ide ├── core │ ├── Overt.Core.DataConsole │ │ ├── appsettings.json │ │ └── Overt.Core.DataConsole.csproj │ ├── Overt.Core.Test │ │ ├── appsettings.json │ │ ├── BaseTest.cs │ │ ├── Overt.Core.Test.csproj │ │ └── ApplicationTest.cs │ ├── Overt.User.Domain │ │ ├── Contracts │ │ │ ├── ISubDbUserRepository.cs │ │ │ ├── IUserLongIdRepository.cs │ │ │ ├── ISubDbUser2Repository.cs │ │ │ ├── ISubUserRepository.cs │ │ │ └── IUserRepository.cs │ │ ├── Overt.User.Domain.csproj │ │ ├── Repositories │ │ │ ├── SubDbUserRepository.cs │ │ │ ├── UserLongIdRepository.cs │ │ │ ├── SubDbUser2Repository.cs │ │ │ ├── UserRepository.cs │ │ │ └── SubUserRepository.cs │ │ ├── ServiceCollectionExtensions.cs │ │ └── Entities │ │ │ ├── UserEntity.cs │ │ │ ├── UserLongIdEntity.cs │ │ │ ├── SubUserEntity.cs │ │ │ ├── SubDbUser2Entity.cs │ │ │ └── SubDbUserEntity.cs │ └── Overt.User.Application │ │ ├── Constracts │ │ ├── ISubDbUser2Service.cs │ │ ├── ISubUserService.cs │ │ ├── ISubDbUserService.cs │ │ ├── IUserLongIdService.cs │ │ └── IUserService.cs │ │ ├── Models │ │ ├── UserModel.cs │ │ ├── UserPostModel.cs │ │ └── UserSearchModel.cs │ │ ├── Overt.User.Application.csproj │ │ ├── ServiceCollectionExtensions.cs │ │ ├── AutoMapperProfiles.cs │ │ ├── Extensions │ │ └── ModelValidationExtensions.cs │ │ └── Services │ │ ├── SubDbUserService.cs │ │ ├── SubDbUser2Service.cs │ │ ├── SubUserService.cs │ │ └── UserLongIdService.cs ├── net46 │ ├── Overt.User.Domain │ │ ├── packages.config │ │ ├── Contracts │ │ │ ├── ISubDbUserRepository.cs │ │ │ ├── ISubDbUser2Repository.cs │ │ │ ├── IUserRepository.cs │ │ │ └── ISubUserRepository.cs │ │ ├── Repositories │ │ │ ├── SubDbUserRepository.cs │ │ │ ├── UserRepository.cs │ │ │ ├── SubDbUser2Repository.cs │ │ │ └── SubUserRepository.cs │ │ ├── AutofacExtensions.cs │ │ ├── Entities │ │ │ ├── UserEntity.cs │ │ │ ├── SubUserEntity.cs │ │ │ ├── SubDbUserEntity.cs │ │ │ └── SubDbUser2Entity.cs │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ └── Overt.User.Domain.csproj │ ├── Overt.User.Application │ │ ├── packages.config │ │ ├── Constracts │ │ │ ├── ISubDbUser2Service.cs │ │ │ ├── ISubUserService.cs │ │ │ ├── ISubDbUserService.cs │ │ │ └── IUserService.cs │ │ ├── Models │ │ │ ├── UserModel.cs │ │ │ ├── UserPostModel.cs │ │ │ └── UserSearchModel.cs │ │ ├── AutofacExtensions.cs │ │ ├── AutoMapperProfiles.cs │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ ├── Services │ │ │ ├── SubDbUserService.cs │ │ │ ├── SubUserService.cs │ │ │ ├── SubDbUser2Service.cs │ │ │ └── UserService.cs │ │ ├── Extensions │ │ │ └── ModelValidationExtensions.cs │ │ └── Overt.User.Application.csproj │ └── Overt.Core.DataConsole │ │ ├── packages.config │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ ├── AutofacContainer.cs │ │ ├── App.config │ │ ├── Program.cs │ │ └── Overt.Core.DataConsole.csproj └── Overt.Core.Data │ ├── Constants.cs │ ├── Enums │ ├── FieldSortType.cs │ ├── DataCustomType.cs │ └── DatabaseType.cs │ ├── Attribute │ └── SubmeterAttribute.cs │ ├── Expressions │ ├── SqlExpression │ │ ├── Resolve │ │ │ ├── NewArraySqlExpression.cs │ │ │ ├── ConstantSqlExpression.cs │ │ │ ├── ListInitSqlExpression.cs │ │ │ ├── NewSqlExpression.cs │ │ │ ├── UnarySqlExpression.cs │ │ │ ├── Basic │ │ │ │ └── ISqlExpression.cs │ │ │ ├── LambdaSqlExpression.cs │ │ │ ├── BinarySqlExpression.cs │ │ │ ├── MethodCallSqlExpression.cs │ │ │ └── MemberSqlExpression.cs │ │ ├── SqlExpressionCompiler.cs │ │ ├── SqlGenerate.cs │ │ ├── SqlExpression.cs │ │ └── SqlExpressionProvider.cs │ └── ExpressionHelper.cs │ ├── Contract │ └── IPropertyAssist.cs │ ├── Extensions │ ├── Expression.Extensions.cs │ ├── Table.Extensions.cs │ ├── EntityDefinition.Extensions.cs │ └── SqlAlias.Extensions.cs │ ├── Params │ └── OrderByField.cs │ ├── Overt.Core.Data.csproj │ ├── Repository │ └── PropertyAssist.cs │ └── DataContext │ ├── DataContext.cs │ └── DataSettings.cs ├── .gitignore ├── core-data.sln └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/.vs/Sodao.Core/v15/Server/sqlite3/db.lock: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/.vs/Sodao.Core/v15/Server/sqlite3/storage.ide: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overtly/core-data/HEAD/src/.vs/Sodao.Core/v15/Server/sqlite3/storage.ide -------------------------------------------------------------------------------- /src/core/Overt.Core.DataConsole/appsettings.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overtly/core-data/HEAD/src/core/Overt.Core.DataConsole/appsettings.json -------------------------------------------------------------------------------- /src/core/Overt.Core.Test/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "ss.master": "Data Source=127.0.0.1;Initial Catalog=TestDb;Persist Security Info=True;User ID=sa;Password=123456;DbType=SqlServer" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Contracts/ISubDbUserRepository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Entities; 3 | 4 | namespace Overt.User.Domain.Contracts 5 | { 6 | public interface ISubDbUserRepository : IBaseRepository 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/Contracts/ISubDbUserRepository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Entities; 3 | 4 | namespace Overt.User.Domain.Contracts 5 | { 6 | public interface ISubDbUserRepository : IBaseRepository 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace Overt.Core.Data 2 | { 3 | internal class Constants 4 | { 5 | public static class MSSQLVersion 6 | { 7 | /// 8 | /// SQLServer2012版本 9 | /// 10 | public const int SQLServer2012Bv = 11; 11 | } 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Contracts/IUserLongIdRepository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Entities; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | 6 | namespace Overt.User.Domain.Contracts 7 | { 8 | public interface IUserLongIdRepository : IBaseRepository 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Enums/FieldSortType.cs: -------------------------------------------------------------------------------- 1 | namespace Overt.Core.Data 2 | { 3 | /// 4 | /// 字段排序类型 5 | /// 6 | public enum FieldSortType 7 | { 8 | /// 9 | /// 顺序 10 | /// 11 | Asc = 1, 12 | /// 13 | /// 倒序 14 | /// 15 | Desc = 2 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Contracts/ISubDbUser2Repository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Entities; 3 | using System; 4 | 5 | namespace Overt.User.Domain.Contracts 6 | { 7 | public interface ISubDbUser2Repository : IBaseRepository 8 | { 9 | /// 10 | /// 分库标识 11 | /// 12 | DateTime SubDbAddTime { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/Contracts/ISubDbUser2Repository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Entities; 3 | using System; 4 | 5 | namespace Overt.User.Domain.Contracts 6 | { 7 | public interface ISubDbUser2Repository : IBaseRepository 8 | { 9 | /// 10 | /// 分库标识 11 | /// 12 | DateTime SubDbAddTime { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/Repositories/SubDbUserRepository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Contracts; 3 | using Overt.User.Domain.Entities; 4 | 5 | namespace Overt.User.Domain.Repositories 6 | { 7 | public class SubDbUserRepository : BaseRepository, ISubDbUserRepository 8 | { 9 | public SubDbUserRepository() 10 | : base("subdb") 11 | { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Overt.User.Domain.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Attribute/SubmeterAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Overt.Core.Data 4 | { 5 | /// 6 | /// 分表标识 7 | /// 8 | [Obsolete("请使用TableNameFunc")] 9 | public class SubmeterAttribute : Attribute 10 | { 11 | /// 12 | /// 16进制位数 13 | /// 1 16 14 | /// 2 256 15 | /// 3 4096 16 | /// ... 17 | /// 18 | public int Bit { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/Constracts/ISubDbUser2Service.cs: -------------------------------------------------------------------------------- 1 | using Overt.User.Application.Models; 2 | using System.Threading.Tasks; 3 | 4 | namespace Overt.User.Application.Constracts 5 | { 6 | public interface ISubDbUser2Service 7 | { 8 | int Add(UserPostModel model); 9 | UserModel Get(int userId, bool isMaster = false); 10 | 11 | Task AddAsync(UserPostModel model); 12 | 13 | Task GetAsync(int userId, bool isMaster = false); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/Constracts/ISubDbUser2Service.cs: -------------------------------------------------------------------------------- 1 | using Overt.User.Application.Models; 2 | using System.Threading.Tasks; 3 | 4 | namespace Overt.User.Application.Constracts 5 | { 6 | public interface ISubDbUser2Service 7 | { 8 | int Add(UserPostModel model); 9 | UserModel Get(int userId, bool isMaster = false); 10 | 11 | Task AddAsync(UserPostModel model); 12 | 13 | Task GetAsync(int userId, bool isMaster = false); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/Constracts/ISubUserService.cs: -------------------------------------------------------------------------------- 1 | using Overt.User.Application.Models; 2 | using Overt.User.Domain.Entities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Overt.User.Application.Constracts 9 | { 10 | public interface ISubUserService 11 | { 12 | Task AddAsync(UserPostModel model); 13 | 14 | Task GetAsync(int userId, bool isMaster = false); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/Constracts/ISubDbUserService.cs: -------------------------------------------------------------------------------- 1 | using Overt.User.Application.Models; 2 | using Overt.User.Domain.Entities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Overt.User.Application.Constracts 9 | { 10 | public interface ISubDbUserService 11 | { 12 | Task AddAsync(UserPostModel model); 13 | 14 | Task GetAsync(int userId, bool isMaster = false); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Enums/DataCustomType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Overt.Core.Data 8 | { 9 | /// 10 | /// 自定义字段类型 11 | /// 12 | public enum DataCustomType 13 | { 14 | /// 15 | /// 未定义 16 | /// 17 | None = 0, 18 | /// 19 | /// jsonb类型 20 | /// 21 | Jsonb = 1, 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/Contracts/IUserRepository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Entities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Overt.User.Domain.Contracts 9 | { 10 | public interface IUserRepository : IBaseRepository 11 | { 12 | /// 13 | /// 其他sql 本案例中 统计UserName去重个数 14 | /// 15 | /// 16 | Task> OtherSqlAsync(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Contracts/ISubUserRepository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Entities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Overt.User.Domain.Contracts 9 | { 10 | public interface ISubUserRepository : IBaseRepository 11 | { 12 | /// 13 | /// 分表标识 第二种 14 | /// 第一种为HASH模式,实体标记Submeter 15 | /// 16 | DateTime AddTime { get; set; } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/Contracts/ISubUserRepository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Entities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Overt.User.Domain.Contracts 9 | { 10 | public interface ISubUserRepository : IBaseRepository 11 | { 12 | /// 13 | /// 分表标识 第二种 14 | /// 第一种为HASH模式,实体标记Submeter 15 | /// 16 | DateTime AddTime { get; set; } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | #ignore thumbnails created by windows 3 | Thumbs.db 4 | #Ignore files build by Visual Studio 5 | *.obj 6 | *.exe 7 | *.pdb 8 | *.user 9 | *.aps 10 | *.pch 11 | *.vspscc 12 | *_i.c 13 | *_p.c 14 | *.ncb 15 | *.suo 16 | *.tlb 17 | *.tlh 18 | *.bak 19 | *.cache 20 | *.ilk 21 | *.log 22 | [Bb]in 23 | [Dd]ebug*/ 24 | *.sbr 25 | obj/ 26 | 27 | [Rr]elease*/ 28 | _ReSharper*/ 29 | [Tt]est[Rr]esult* 30 | packages 31 | 32 | 33 | log.txt 34 | /.vs 35 | /src/core/Overt.Core.DataConsole/appsettings.txt 36 | /src/net46/Overt.Core.DataConsole/App.txt 37 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/Constracts/ISubUserService.cs: -------------------------------------------------------------------------------- 1 | using Overt.User.Application.Models; 2 | using Overt.User.Domain.Entities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Overt.User.Application.Constracts 9 | { 10 | public interface ISubUserService 11 | { 12 | int Add(UserPostModel model); 13 | 14 | UserModel Get(int userId, bool isMaster = false); 15 | 16 | Task AddAsync(UserPostModel model); 17 | 18 | Task GetAsync(int userId, bool isMaster = false); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/Constracts/ISubDbUserService.cs: -------------------------------------------------------------------------------- 1 | using Overt.User.Application.Models; 2 | using Overt.User.Domain.Entities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Overt.User.Application.Constracts 9 | { 10 | public interface ISubDbUserService 11 | { 12 | 13 | int Add(UserPostModel model); 14 | 15 | UserModel Get(int userId, bool isMaster = false); 16 | 17 | Task AddAsync(UserPostModel model); 18 | 19 | Task GetAsync(int userId, bool isMaster = false); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Repositories/SubDbUserRepository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Contracts; 3 | using Overt.User.Domain.Entities; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | using Dapper; 8 | using System.Linq; 9 | using Microsoft.Extensions.Configuration; 10 | 11 | namespace Overt.User.Domain.Repositories 12 | { 13 | public class SubDbUserRepository : BaseRepository, ISubDbUserRepository 14 | { 15 | public SubDbUserRepository(IConfiguration configuration) 16 | : base(configuration, "subdb") 17 | { 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Enums/DatabaseType.cs: -------------------------------------------------------------------------------- 1 | namespace Overt.Core.Data 2 | { 3 | /// 4 | /// 数据库类型 5 | /// 6 | public enum DatabaseType 7 | { 8 | /// 9 | /// SqlServer 10 | /// 11 | SqlServer, 12 | /// 13 | /// >=SqlServer2012 14 | /// 15 | GteSqlServer2012, 16 | /// 17 | /// Mysql 18 | /// 19 | MySql, 20 | /// 21 | /// Sqlite 22 | /// 23 | SQLite, 24 | /// 25 | /// PostgreSQL 26 | /// 27 | PostgreSQL 28 | } 29 | } -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Contracts/IUserRepository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Entities; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | 6 | namespace Overt.User.Domain.Contracts 7 | { 8 | public interface IUserRepository : IBaseRepository 9 | { 10 | /// 11 | /// 其他sql 本案例中 统计UserName去重个数 12 | /// 13 | /// 14 | List OtherSql(); 15 | 16 | /// 17 | /// 其他sql 本案例中 统计UserName去重个数 18 | /// 19 | /// 20 | Task> OtherSqlAsync(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/AutofacExtensions.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Overt.User.Domain.Contracts; 3 | using Overt.User.Domain.Repositories; 4 | 5 | namespace Overt.User.Domain 6 | { 7 | public static class AutofacExtensions 8 | { 9 | public static void AddDomainDI(this ContainerBuilder builder) 10 | { 11 | builder.RegisterType().As(); 12 | builder.RegisterType().As(); 13 | builder.RegisterType().As(); 14 | builder.RegisterType().As(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Repositories/UserLongIdRepository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Contracts; 3 | using Overt.User.Domain.Entities; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | using Dapper; 8 | using System.Linq; 9 | using Microsoft.Extensions.Configuration; 10 | 11 | namespace Overt.User.Domain.Repositories 12 | { 13 | public class UserLongIdRepository : BaseRepository, IUserLongIdRepository 14 | { 15 | public UserLongIdRepository(IConfiguration configuration) 16 | : base(configuration) // dbStoreKey 可用于不同数据库切换,连接字符串key前缀:xxx.master xxx.secondary 17 | { 18 | } 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/Models/UserModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Text; 6 | 7 | namespace Overt.User.Application.Models 8 | { 9 | public class UserModel 10 | { 11 | public int UserId { get; set; } 12 | public string UserName { get; set; } 13 | public string RealName { get; set; } 14 | public string Password { get; set; } 15 | public DateTime AddTime { get; set; } 16 | public bool IsSex { get; set; } 17 | /// 18 | /// Json类型 19 | /// 20 | public string JsonValue { get; set; } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/Models/UserModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Text; 6 | 7 | namespace Overt.User.Application.Models 8 | { 9 | public class UserModel 10 | { 11 | public int UserId { get; set; } 12 | public string UserName { get; set; } 13 | public string RealName { get; set; } 14 | public string Password { get; set; } 15 | public DateTime AddTime { get; set; } 16 | public bool IsSex { get; set; } 17 | /// 18 | /// Json类型 19 | /// 20 | public string JsonValue { get; set; } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/AutofacExtensions.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Overt.User.Application.Constracts; 3 | using Overt.User.Application.Services; 4 | using Overt.User.Domain; 5 | 6 | namespace Overt.User.Application 7 | { 8 | public static class AutofacExtensions 9 | { 10 | public static void AddApplicationDI(this ContainerBuilder builder) 11 | { 12 | builder.RegisterType().As(); 13 | builder.RegisterType().As(); 14 | builder.RegisterType().As(); 15 | builder.RegisterType().As(); 16 | 17 | builder.AddDomainDI(); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/SqlExpression/Resolve/NewArraySqlExpression.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq.Expressions; 3 | 4 | namespace Overt.Core.Data.Expressions 5 | { 6 | class NewArraySqlExpression : BaseSqlExpression 7 | { 8 | protected override SqlGenerate In(NewArrayExpression expression, SqlGenerate sqlGenerate) 9 | { 10 | var list = new List(); 11 | foreach (var expressionItem in expression.Expressions) 12 | { 13 | var obj = SqlExpressionCompiler.Evaluate(expressionItem); 14 | list.Add(obj); 15 | } 16 | sqlGenerate.AddDbParameter(list); 17 | return sqlGenerate; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/Entities/UserEntity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Text; 6 | 7 | namespace Overt.User.Domain.Entities 8 | { 9 | [Table("User")] 10 | public class UserEntity 11 | { 12 | [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 13 | public int UserId { get; set; } 14 | public string UserName { get; set; } 15 | public string RealName { get; set; } 16 | public string Password { get; set; } 17 | public DateTime AddTime { get; set; } 18 | public bool IsSex { get; set; } 19 | /// 20 | /// Json类型 21 | /// 22 | public string JsonValue { get; set; } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/Overt.User.Application.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.dependencyinjection.abstractions\2.0.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/core/Overt.Core.Test/BaseTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Overt.User.Application; 4 | using System; 5 | 6 | namespace Overt.Core.Test 7 | { 8 | public class BaseTest 9 | { 10 | public IServiceProvider provider; 11 | public BaseTest() 12 | { 13 | var builder = new ConfigurationBuilder() 14 | .SetBasePath(AppContext.BaseDirectory) 15 | .AddJsonFile("appsettings.json", true); 16 | 17 | var configuration = builder.Build(); 18 | 19 | var services = new ServiceCollection(); 20 | services.AddSingleton(configuration); 21 | services.AddApplicationDI(); 22 | 23 | provider = services.BuildServiceProvider(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/net46/Overt.Core.DataConsole/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Overt.User.Domain.Contracts; 3 | using Overt.User.Domain.Repositories; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace Overt.User.Domain 9 | { 10 | public static class ServiceCollectionExtensions 11 | { 12 | public static void AddDomainDI(this IServiceCollection services) 13 | { 14 | services.AddTransient(); 15 | services.AddTransient(); 16 | services.AddTransient(); 17 | services.AddTransient(); 18 | services.AddTransient(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/Constracts/IUserService.cs: -------------------------------------------------------------------------------- 1 | using Overt.User.Application.Models; 2 | using Overt.User.Domain.Entities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Overt.User.Application.Constracts 9 | { 10 | public interface IUserService 11 | { 12 | Task GetAsync(int userId, bool isMaster = false); 13 | 14 | Task> GetListAsync(List userIds, bool isMaster = false); 15 | 16 | Task<(int, List)> GetPageAsync(UserSearchModel model); 17 | 18 | Task AddAsync(UserPostModel model); 19 | 20 | Task UpdateAsync(int userId, bool isSex); 21 | 22 | Task DeleteAsync(int userId); 23 | 24 | Task> OtherSqlAsync(); 25 | 26 | Task ExecuteInTransactionAsync(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/Entities/SubUserEntity.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace Overt.User.Domain.Entities 7 | { 8 | [Table("User")] 9 | public class SubUserEntity 10 | { 11 | // 第一种分表标识,Md5(UserId)取{Bit}位 尽量不用,使用自定义模式 12 | //[Submeter(Bit = 2)] 13 | [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 14 | public int UserId { get; set; } 15 | public string UserName { get; set; } 16 | public string RealName { get; set; } 17 | public string Password { get; set; } 18 | public DateTime AddTime { get; set; } 19 | public bool IsSex { get; set; } 20 | /// 21 | /// Json类型 22 | /// 23 | public string JsonValue { get; set; } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/Entities/SubDbUserEntity.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace Overt.User.Domain.Entities 7 | { 8 | [Table("User")] 9 | public class SubDbUserEntity 10 | { 11 | // 第一种分表标识,Md5(UserId)取{Bit}位 尽量不用,使用自定义模式 12 | //[Submeter(Bit = 2)] 13 | [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 14 | public int UserId { get; set; } 15 | public string UserName { get; set; } 16 | public string RealName { get; set; } 17 | public string Password { get; set; } 18 | public DateTime AddTime { get; set; } 19 | public bool IsSex { get; set; } 20 | /// 21 | /// Json类型 22 | /// 23 | public string JsonValue { get; set; } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/AutoMapperProfiles.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Overt.User.Application.Models; 3 | using Overt.User.Domain.Entities; 4 | 5 | namespace Overt.User.Application 6 | { 7 | public class AutoMapperProfiles : Profile 8 | { 9 | public AutoMapperProfiles() 10 | { 11 | #region Input 12 | CreateMap(); 13 | CreateMap(); 14 | CreateMap(); 15 | CreateMap(); 16 | #endregion 17 | 18 | #region Output 19 | CreateMap(); 20 | CreateMap(); 21 | CreateMap(); 22 | CreateMap(); 23 | #endregion 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Overt.User.Application.Constracts; 4 | using Overt.User.Application.Services; 5 | using Overt.User.Domain; 6 | 7 | namespace Overt.User.Application 8 | { 9 | public static class ServiceCollectionExtensions 10 | { 11 | public static void AddApplicationDI(this IServiceCollection services) 12 | { 13 | services.AddTransient(); 14 | services.AddTransient(); 15 | services.AddTransient(); 16 | services.AddTransient(); 17 | services.AddTransient(); 18 | 19 | services.AddDomainDI(); 20 | services.AddAutoMapper(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Entities/UserEntity.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.ComponentModel.DataAnnotations.Schema; 6 | using System.Text; 7 | 8 | namespace Overt.User.Domain.Entities 9 | { 10 | [Table("User")] 11 | public class UserEntity 12 | { 13 | [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 14 | public int UserId { get; set; } 15 | 16 | public string UserName { get; set; } 17 | public string RealName { get; set; } 18 | public string Password { get; set; } 19 | public DateTime AddTime { get; set; } 20 | public bool IsSex { get; set; } 21 | /// 22 | /// 23 | /// 24 | public int Age { get; set; } 25 | /// 26 | /// Json类型 27 | /// 28 | public string JsonValue { get; set; } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Entities/UserLongIdEntity.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.ComponentModel.DataAnnotations.Schema; 6 | using System.Text; 7 | 8 | namespace Overt.User.Domain.Entities 9 | { 10 | [Table("UserLongId")] 11 | public class UserLongIdEntity 12 | { 13 | [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 14 | public long UserId { get; set; } 15 | 16 | public string UserName { get; set; } 17 | public string RealName { get; set; } 18 | public string Password { get; set; } 19 | public DateTime AddTime { get; set; } 20 | public bool IsSex { get; set; } 21 | /// 22 | /// 23 | /// 24 | public int Age { get; set; } 25 | /// 26 | /// Json类型 27 | /// 28 | public string JsonValue { get; set; } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Entities/SubUserEntity.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace Overt.User.Domain.Entities 7 | { 8 | [Table("User")] 9 | public class SubUserEntity 10 | { 11 | // 第一种分表标识,Md5(UserId)取{Bit}位 尽量不用,使用自定义模式 12 | //[Submeter(Bit = 2)] 13 | [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 14 | public int UserId { get; set; } 15 | public string UserName { get; set; } 16 | public string RealName { get; set; } 17 | public string Password { get; set; } 18 | public DateTime AddTime { get; set; } 19 | public bool IsSex { get; set; } 20 | /// 21 | /// 22 | /// 23 | public int Age { get; set; } 24 | /// 25 | /// Json类型 26 | /// 27 | public string JsonValue { get; set; } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Entities/SubDbUser2Entity.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace Overt.User.Domain.Entities 7 | { 8 | [Table("User")] 9 | public class SubDbUser2Entity 10 | { 11 | // 第一种分表标识,Md5(UserId)取{Bit}位 尽量不用,使用自定义模式 12 | //[Submeter(Bit = 2)] 13 | [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 14 | public int UserId { get; set; } 15 | public string UserName { get; set; } 16 | public string RealName { get; set; } 17 | public string Password { get; set; } 18 | public DateTime AddTime { get; set; } 19 | public bool IsSex { get; set; } 20 | /// 21 | /// 22 | /// 23 | public int Age { get; set; } 24 | /// 25 | /// Json类型 26 | /// 27 | public string JsonValue { get; set; } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Entities/SubDbUserEntity.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace Overt.User.Domain.Entities 7 | { 8 | [Table("User")] 9 | public class SubDbUserEntity 10 | { 11 | // 第一种分表标识,Md5(UserId)取{Bit}位 尽量不用,使用自定义模式 12 | //[Submeter(Bit = 2)] 13 | [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 14 | public int UserId { get; set; } 15 | public string UserName { get; set; } 16 | public string RealName { get; set; } 17 | public string Password { get; set; } 18 | public DateTime AddTime { get; set; } 19 | public bool IsSex { get; set; } 20 | /// 21 | /// 22 | /// 23 | public int Age { get; set; } 24 | /// 25 | /// Json类型 26 | /// 27 | public string JsonValue { get; set; } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/Entities/SubDbUser2Entity.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace Overt.User.Domain.Entities 7 | { 8 | [Table("User")] 9 | public class SubDbUser2Entity 10 | { 11 | // 第一种分表标识,Md5(UserId)取{Bit}位 尽量不用,使用自定义模式 12 | //[Submeter(Bit = 2)] 13 | [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 14 | public int UserId { get; set; } 15 | public string UserName { get; set; } 16 | public string RealName { get; set; } 17 | public string Password { get; set; } 18 | public DateTime AddTime { get; set; } 19 | public bool IsSex { get; set; } 20 | /// 21 | /// 22 | /// 23 | public int Age { get; set; } 24 | /// 25 | /// Json类型 26 | /// 27 | public string JsonValue { get; set; } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/AutoMapperProfiles.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Overt.User.Application.Models; 3 | using Overt.User.Domain.Entities; 4 | 5 | namespace Overt.User.Application 6 | { 7 | public class AutoMapperProfiles : Profile 8 | { 9 | public AutoMapperProfiles() 10 | { 11 | #region Input 12 | CreateMap(); 13 | CreateMap(); 14 | CreateMap(); 15 | CreateMap(); 16 | CreateMap(); 17 | #endregion 18 | 19 | #region Output 20 | CreateMap(); 21 | CreateMap(); 22 | CreateMap(); 23 | CreateMap(); 24 | CreateMap(); 25 | #endregion 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/Constracts/IUserLongIdService.cs: -------------------------------------------------------------------------------- 1 | using Overt.User.Application.Models; 2 | using Overt.User.Domain.Entities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Overt.User.Application.Constracts 9 | { 10 | public interface IUserLongIdService 11 | { 12 | #region SyncMethod 13 | UserModel Get(long userId, bool isMaster = false); 14 | 15 | List GetList(List userIds, bool isMaster = false); 16 | 17 | long Add(UserPostModel model); 18 | 19 | bool Add(params UserPostModel[] models); 20 | #endregion 21 | 22 | #region AsyncMethod 23 | Task GetAsync(long userId, bool isMaster = false); 24 | 25 | Task> GetListAsync(List userIds, bool isMaster = false); 26 | 27 | Task AddAsync(UserPostModel model); 28 | 29 | Task AddAsync(params UserPostModel[] models); 30 | #endregion 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/Repositories/UserRepository.cs: -------------------------------------------------------------------------------- 1 | using Dapper; 2 | using Overt.Core.Data; 3 | using Overt.User.Domain.Contracts; 4 | using Overt.User.Domain.Entities; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace Overt.User.Domain.Repositories 10 | { 11 | public class UserRepository : BaseRepository, IUserRepository 12 | { 13 | public UserRepository() 14 | : base() // dbStoreKey 可用于不同数据库切换,连接字符串key前缀:xxx.master xxx.secondary 15 | { 16 | } 17 | 18 | public async Task> OtherSqlAsync() 19 | { 20 | // 表名最好使用这个方法获取,支持分表,分表案例详见其他案例 21 | var tableName = GetTableName(); 22 | var sql = $"select distinct([UserName]) from [{tableName}]"; 23 | return await Execute(async connecdtion => 24 | { 25 | var task = await connecdtion.QueryAsync(sql); 26 | return task.ToList(); 27 | }); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("Overt.User.Domain")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("Overt.User.Domain")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("f34f6b13-b939-47a3-827e-e7015fd1b434")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/net46/Overt.Core.DataConsole/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("Overt.Core.DataConsole")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("Overt.Core.DataConsole")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("f92f116b-a438-447b-9475-4d62af197742")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | // 方法是按如下所示使用“*”: : 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("Overt.User.Application")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("Overt.User.Application")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("5adb2a33-42e4-484b-997e-3f8b942539e4")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/SqlExpression/Resolve/ConstantSqlExpression.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq.Expressions; 3 | 4 | namespace Overt.Core.Data.Expressions 5 | { 6 | class ConstantSqlExpression : BaseSqlExpression 7 | { 8 | protected override SqlGenerate Where(ConstantExpression expression, SqlGenerate sqlGenerate) 9 | { 10 | sqlGenerate.AddDbParameter(expression.Value); 11 | return sqlGenerate; 12 | } 13 | 14 | protected override SqlGenerate In(ConstantExpression expression, SqlGenerate sqlGenerate) 15 | { 16 | sqlGenerate.AddDbParameter(expression.Value); 17 | sqlGenerate += ","; 18 | return sqlGenerate; 19 | } 20 | 21 | protected override SqlGenerate Select(ConstantExpression expression, SqlGenerate sqlGenerate) 22 | { 23 | if (expression.Value == null) 24 | sqlGenerate.SelectFields = new List() { "*" }; 25 | else 26 | sqlGenerate.SelectFields = new List() { expression.Value.ToString() }; 27 | return sqlGenerate; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/net46/Overt.Core.DataConsole/AutofacContainer.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using AutoMapper; 3 | using Overt.User.Application; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Overt.Core.DataConsole 11 | { 12 | public class AutofacContainer 13 | { 14 | public static IContainer Container { get; private set; } 15 | 16 | public static IContainer Register() 17 | { 18 | var builder = new ContainerBuilder(); 19 | builder.AddApplicationDI(); 20 | 21 | 22 | builder.RegisterType().As(); 23 | builder.Register(c => new MapperConfiguration(cfg => 24 | { 25 | foreach (var profile in c.Resolve>()) 26 | { 27 | cfg.AddProfile(profile); 28 | } 29 | })).AsSelf().SingleInstance(); 30 | builder.Register(c => c.Resolve().CreateMapper(c.Resolve)).As().InstancePerLifetimeScope(); 31 | 32 | Container = builder.Build(Autofac.Builder.ContainerBuildOptions.None); 33 | return Container; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/Repositories/SubDbUser2Repository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Contracts; 3 | using Overt.User.Domain.Entities; 4 | using System; 5 | using System.Configuration; 6 | 7 | namespace Overt.User.Domain.Repositories 8 | { 9 | public class SubDbUser2Repository : BaseRepository, ISubDbUser2Repository 10 | { 11 | public SubDbUser2Repository() 12 | : base() 13 | { 14 | } 15 | 16 | 17 | // Service层进行赋值即可 18 | public DateTime SubDbAddTime { get; set; } 19 | 20 | public override Func ConnectionFunc => (isMaster) => 21 | { 22 | var connectionString = string.Empty; 23 | 24 | var dbName = $"TestDb_{SubDbAddTime.ToString("yyyy")}"; 25 | if (isMaster) 26 | connectionString = $"Data Source=127.0.0.1;Initial Catalog={dbName};Persist Security Info=True;User ID=sa;Password=123465"; 27 | else 28 | connectionString = $"Data Source=127.0.0.1;Initial Catalog={dbName};Persist Security Info=True;User ID=sa;Password=123465"; 29 | return new ConnectionStringSettings(dbName, connectionString, "System.Data.SqlClient"); 30 | }; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/Models/UserPostModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Overt.User.Application.Models 9 | { 10 | public class UserPostModel : IValidatableObject 11 | { 12 | public string UserName { get; set; } 13 | public string RealName { get; set; } 14 | public string Password { get; set; } 15 | public DateTime AddTime { get; set; } 16 | public bool IsSex { get; set; } 17 | /// 18 | /// Json类型 19 | /// 20 | public string JsonValue { get; set; } 21 | 22 | 23 | /// 24 | /// 验证方法 25 | /// 26 | /// 27 | /// 28 | public virtual IEnumerable Validate(ValidationContext validationContext) 29 | { 30 | if (string.IsNullOrWhiteSpace(UserName)) 31 | yield return new ValidationResult("用户名必须提供", new[] { nameof(UserName) }); 32 | 33 | if (string.IsNullOrWhiteSpace(Password)) 34 | yield return new ValidationResult("密码必须提供", new[] { nameof(Password) }); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/Models/UserPostModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Overt.User.Application.Models 9 | { 10 | public class UserPostModel : IValidatableObject 11 | { 12 | public string UserName { get; set; } 13 | public string RealName { get; set; } 14 | public string Password { get; set; } 15 | public DateTime AddTime { get; set; } 16 | public bool IsSex { get; set; } 17 | /// 18 | /// Json类型 19 | /// 20 | public string JsonValue { get; set; } 21 | 22 | 23 | /// 24 | /// 验证方法 25 | /// 26 | /// 27 | /// 28 | public virtual IEnumerable Validate(ValidationContext validationContext) 29 | { 30 | if (string.IsNullOrWhiteSpace(UserName)) 31 | yield return new ValidationResult("用户名必须提供", new[] { nameof(UserName) }); 32 | 33 | if (string.IsNullOrWhiteSpace(Password)) 34 | yield return new ValidationResult("密码必须提供", new[] { nameof(Password) }); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Repositories/SubDbUser2Repository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Contracts; 3 | using Overt.User.Domain.Entities; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | using Dapper; 8 | using System.Linq; 9 | using Microsoft.Extensions.Configuration; 10 | 11 | namespace Overt.User.Domain.Repositories 12 | { 13 | public class SubDbUser2Repository : BaseRepository, ISubDbUser2Repository 14 | { 15 | public SubDbUser2Repository(IConfiguration configuration) 16 | : base(configuration) 17 | { 18 | } 19 | 20 | 21 | // Service层进行赋值即可 22 | public DateTime SubDbAddTime { get; set; } 23 | 24 | public override Func ConnectionFunc => (isMaster) => 25 | { 26 | var connectionString = string.Empty; 27 | 28 | var dbName = $"TestDb_{SubDbAddTime.ToString("yyyy")}"; 29 | if (isMaster) 30 | connectionString = $"Data Source=127.0.0.1;Initial Catalog={dbName};Persist Security Info=True;User ID=sa;Password=123465;DbType=SqlServer"; 31 | else 32 | connectionString = $"Data Source=127.0.0.1;Initial Catalog={dbName};Persist Security Info=True;User ID=sa;Password=123465;DbType=SqlServer"; 33 | return connectionString; 34 | }; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/Models/UserSearchModel.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Entities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Overt.User.Application.Models 11 | { 12 | public class UserSearchModel 13 | { 14 | public int Page { get; set; } 15 | 16 | public int Size { get; set; } 17 | 18 | public bool IsMaster { get; set; } 19 | 20 | public List UserIds { get; set; } 21 | 22 | public string SearchKey { get; set; } 23 | 24 | public Expression> GetExpression() 25 | { 26 | Expression> expression = oo => oo.UserId > 0; 27 | if (UserIds?.Count > 0) 28 | expression = expression.And(oo => UserIds.Contains(oo.UserId)); 29 | 30 | if (!string.IsNullOrEmpty(SearchKey)) 31 | expression = expression.And(oo => oo.UserName.Contains(SearchKey)); 32 | 33 | return expression; 34 | } 35 | 36 | public OrderByField[] GetOrder() 37 | { 38 | var list = new List() 39 | { 40 | OrderByField.Create(nameof(UserEntity.AddTime), FieldSortType.Asc) 41 | }; 42 | return list.ToArray(); 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/Models/UserSearchModel.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Entities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Overt.User.Application.Models 11 | { 12 | public class UserSearchModel 13 | { 14 | public int Page { get; set; } 15 | 16 | public int Size { get; set; } 17 | 18 | public bool IsMaster { get; set; } 19 | 20 | public List UserIds { get; set; } 21 | 22 | public string SearchKey { get; set; } 23 | 24 | public Expression> GetExpression() 25 | { 26 | Expression> expression = oo => oo.UserId > 0; 27 | if (UserIds?.Count > 0) 28 | expression = expression.And(oo => UserIds.Contains(oo.UserId)); 29 | 30 | if (!string.IsNullOrEmpty(SearchKey)) 31 | expression = expression.And(oo => oo.UserName.Contains(SearchKey)); 32 | 33 | return expression; 34 | } 35 | 36 | public OrderByField[] GetOrder() 37 | { 38 | var list = new List() 39 | { 40 | OrderByField.Create(nameof(UserEntity.AddTime), FieldSortType.Asc) 41 | }; 42 | return list.ToArray(); 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/core/Overt.Core.DataConsole/Overt.Core.DataConsole.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.dependencyinjection\2.0.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.dll 21 | 22 | 23 | 24 | 25 | 26 | Always 27 | 28 | 29 | Always 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/Repositories/SubUserRepository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Contracts; 3 | using Overt.User.Domain.Entities; 4 | using System; 5 | 6 | namespace Overt.User.Domain.Repositories 7 | { 8 | public class SubUserRepository : BaseRepository, ISubUserRepository 9 | { 10 | public SubUserRepository() : base() 11 | { 12 | } 13 | 14 | // Service层进行赋值即可 15 | public DateTime AddTime { get; set; } 16 | 17 | public override Func TableNameFunc => () => 18 | { 19 | var tableName = $"{GetMainTableName()}_{DateTime.Now.ToString("yyyyMMdd")}"; 20 | return tableName; 21 | }; 22 | 23 | public override Func CreateScriptFunc => (tableName) => 24 | { 25 | return $"CREATE TABLE [{tableName}] (" + 26 | " [UserId] int IDENTITY(1,1) NOT NULL," + 27 | " [UserName] varchar(200) COLLATE Chinese_PRC_CI_AS DEFAULT NULL NULL," + 28 | " [Password] varchar(200) COLLATE Chinese_PRC_CI_AS DEFAULT NULL NULL," + 29 | " [RealName] varchar(200) COLLATE Chinese_PRC_CI_AS DEFAULT NULL NULL," + 30 | " [AddTime] datetime DEFAULT NULL NULL," + 31 | " [IsSex] bit DEFAULT NULL NULL," + 32 | " [JsonValue] varchar(1000) COLLATE Chinese_PRC_CI_AS DEFAULT NULL NULL" + 33 | ") "; 34 | }; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/core/Overt.Core.Test/Overt.Core.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.dependencyinjection\2.0.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.dll 23 | 24 | 25 | C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.dependencyinjection.abstractions\2.0.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll 26 | 27 | 28 | 29 | 30 | 31 | Always 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/Services/SubDbUserService.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Overt.User.Application.Constracts; 3 | using Overt.User.Application.Models; 4 | using Overt.User.Domain.Contracts; 5 | using Overt.User.Domain.Entities; 6 | using System; 7 | using System.Threading.Tasks; 8 | 9 | namespace Overt.User.Application.Services 10 | { 11 | public class SubDbUserService : ISubDbUserService 12 | { 13 | IMapper _mapper; 14 | ISubDbUserRepository _repository; 15 | public SubDbUserService( 16 | IMapper mapper, 17 | ISubDbUserRepository repository) 18 | { 19 | _mapper = mapper; 20 | _repository = repository; 21 | } 22 | 23 | public async Task AddAsync(UserPostModel model) 24 | { 25 | if (!model.IsValid(out Exception ex)) 26 | throw ex; 27 | 28 | var entity = _mapper.Map(model); 29 | entity.AddTime = DateTime.Now; 30 | var result = await _repository.AddAsync(entity, true); 31 | if (!result) 32 | throw new Exception($"新增失败"); 33 | return entity.UserId; 34 | } 35 | 36 | public async Task GetAsync(int userId, bool isMaster = false) 37 | { 38 | if (userId <= 0) 39 | throw new Exception($"UserId必须大于0"); 40 | 41 | var entity = await _repository.GetAsync(oo => oo.UserId == userId, isMaster: isMaster); 42 | return _mapper.Map(entity); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Repositories/UserRepository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Contracts; 3 | using Overt.User.Domain.Entities; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | using Dapper; 8 | using System.Linq; 9 | using Microsoft.Extensions.Configuration; 10 | 11 | namespace Overt.User.Domain.Repositories 12 | { 13 | public class UserRepository : BaseRepository, IUserRepository 14 | { 15 | public UserRepository(IConfiguration configuration) 16 | : base(configuration) // dbStoreKey 可用于不同数据库切换,连接字符串key前缀:xxx.master xxx.secondary 17 | { 18 | } 19 | 20 | public List OtherSql() 21 | { 22 | // 表名最好使用这个方法获取,支持分表,分表案例详见其他案例 23 | var tableName = GetTableName(); 24 | var sql = $"select distinct([UserName]) from [{tableName}]"; 25 | return Execute(connecdtion => 26 | { 27 | var task = connecdtion.Query(sql); 28 | return task.ToList(); 29 | }); 30 | } 31 | 32 | public async Task> OtherSqlAsync() 33 | { 34 | // 表名最好使用这个方法获取,支持分表,分表案例详见其他案例 35 | var tableName = GetTableName(); 36 | var sql = $"select distinct([UserName]) from [{tableName}]"; 37 | return await Execute(async connecdtion => 38 | { 39 | var task = await connecdtion.QueryAsync(sql); 40 | return task.ToList(); 41 | }); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Contract/IPropertyAssist.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | #if !ASP_NET_CORE 4 | using System.Configuration; 5 | #endif 6 | 7 | namespace Overt.Core.Data 8 | { 9 | /// 10 | /// 通用的接口 11 | /// 12 | public interface IPropertyAssist 13 | { 14 | #region DbStoreKey 15 | /// 16 | /// 数据库key 17 | /// 18 | string DbStoreKey { get; set; } 19 | #endregion 20 | 21 | #region TableName 22 | /// 23 | /// 表名生成方法 24 | /// 25 | Func TableNameFunc { get; set; } 26 | 27 | /// 28 | /// 创建表的sql语句 29 | /// 参数:表名 30 | /// 31 | Func CreateScriptFunc { get; set; } 32 | #endregion 33 | 34 | #region ConnectionString 35 | /// 36 | /// 连接方法创建 37 | /// 38 | 39 | #if ASP_NET_CORE 40 | Func ConnectionFunc { get; set; } 41 | #else 42 | Func ConnectionFunc { get; set; } 43 | #endif 44 | #endregion 45 | 46 | #region Connection 47 | /// 48 | /// 打开连接 49 | /// 50 | /// 51 | IDbConnection OpenConnection(bool isMaster = false); 52 | #endregion 53 | 54 | #region ExecuteScript 55 | /// 56 | /// 执行的sql脚本 57 | /// 58 | string ExecuteScript { get; set; } 59 | #endregion 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Extensions/Expression.Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | 5 | namespace Overt.Core.Data 6 | { 7 | /// 8 | /// expression 扩展 9 | /// 10 | public static class ExpressionExtensions 11 | { 12 | /// 13 | /// and 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | public static Expression> And(this Expression> expr1, 20 | Expression> expr2) 21 | { 22 | var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast()); 23 | return Expression.Lambda> 24 | (Expression.AndAlso(expr1.Body, expr2.Body), expr1.Parameters); 25 | } 26 | 27 | /// 28 | /// or 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | public static Expression> Or(this Expression> expr1, 35 | Expression> expr2) 36 | { 37 | var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast()); 38 | return Expression.Lambda> 39 | (Expression.OrElse(expr1.Body, expr2.Body), expr1.Parameters); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/SqlExpression/Resolve/ListInitSqlExpression.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq.Expressions; 3 | 4 | namespace Overt.Core.Data.Expressions 5 | { 6 | class ListInitSqlExpression : BaseSqlExpression 7 | { 8 | protected override SqlGenerate In(ListInitExpression expression, SqlGenerate sqlGenerate) 9 | { 10 | var list = new List(); 11 | foreach (var elementInit in expression.Initializers) 12 | { 13 | foreach (var expre in elementInit.Arguments) 14 | { 15 | var obj = SqlExpressionCompiler.Evaluate(expre); 16 | list.Add(obj); 17 | } 18 | } 19 | sqlGenerate.AddDbParameter(list); 20 | return sqlGenerate; 21 | } 22 | 23 | protected override SqlGenerate Select(ListInitExpression expression, SqlGenerate sqlGenerate) 24 | { 25 | foreach (var elementInit in expression.Initializers) 26 | { 27 | foreach (var expre in elementInit.Arguments) 28 | { 29 | var obj = SqlExpressionCompiler.Evaluate(expre); 30 | if (obj == null) 31 | continue; 32 | 33 | var fieldName = obj.ToString(); 34 | if (string.IsNullOrEmpty(fieldName)) 35 | continue; 36 | sqlGenerate.SelectFields.Add(fieldName.ParamSql(sqlGenerate)); 37 | } 38 | } 39 | return sqlGenerate; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/core/Overt.User.Domain/Repositories/SubUserRepository.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data; 2 | using Overt.User.Domain.Contracts; 3 | using Overt.User.Domain.Entities; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | using Dapper; 8 | using System.Linq; 9 | using Microsoft.Extensions.Configuration; 10 | 11 | namespace Overt.User.Domain.Repositories 12 | { 13 | public class SubUserRepository : BaseRepository, ISubUserRepository 14 | { 15 | public SubUserRepository(IConfiguration configuration) : base(configuration) 16 | { 17 | } 18 | 19 | // Service层进行赋值即可 20 | public DateTime AddTime { get; set; } 21 | 22 | public override Func TableNameFunc => () => 23 | { 24 | var tableName = $"{GetMainTableName()}_{AddTime.ToString("yyyyMMdd")}"; 25 | return tableName; 26 | }; 27 | 28 | public override Func CreateScriptFunc => (tableName) => 29 | { 30 | return $"CREATE TABLE [{tableName}] (" + 31 | " [UserId] int IDENTITY(1,1) NOT NULL," + 32 | " [UserName] varchar(200) COLLATE Chinese_PRC_CI_AS DEFAULT NULL NULL," + 33 | " [Password] varchar(200) COLLATE Chinese_PRC_CI_AS DEFAULT NULL NULL," + 34 | " [RealName] varchar(200) COLLATE Chinese_PRC_CI_AS DEFAULT NULL NULL," + 35 | " [AddTime] datetime DEFAULT NULL NULL," + 36 | " [IsSex] bit DEFAULT NULL NULL," + 37 | " [Age] int DEFAULT 0 NOT NULL," + 38 | " [JsonValue] varchar(1000) COLLATE Chinese_PRC_CI_AS DEFAULT NULL NULL" + 39 | ") "; 40 | }; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/Constracts/IUserService.cs: -------------------------------------------------------------------------------- 1 | using Overt.User.Application.Models; 2 | using Overt.User.Domain.Entities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Overt.User.Application.Constracts 9 | { 10 | public interface IUserService 11 | { 12 | #region SyncMethod 13 | UserModel Get(int userId, bool isMaster = false); 14 | 15 | List GetList(List userIds, bool isMaster = false); 16 | 17 | (int, List) GetPage(UserSearchModel model); 18 | 19 | int Add(UserPostModel model); 20 | 21 | bool Add(params UserPostModel[] models); 22 | 23 | bool Update(int userId, bool isSex); 24 | 25 | bool Delete(int userId); 26 | 27 | List OtherSql(); 28 | 29 | /// 30 | /// 在事务中执行 31 | /// 32 | /// 33 | bool ExecuteInTransaction(); 34 | #endregion 35 | 36 | #region AsyncMethod 37 | Task GetAsync(int userId, bool isMaster = false); 38 | 39 | Task> GetListAsync(List userIds, bool isMaster = false); 40 | 41 | Task<(int, List)> GetPageAsync(UserSearchModel model); 42 | 43 | Task AddAsync(UserPostModel model); 44 | 45 | Task AddAsync(params UserPostModel[] models); 46 | 47 | Task UpdateAsync(int userId, bool isSex); 48 | 49 | Task DeleteAsync(int userId); 50 | 51 | Task> OtherSqlAsync(); 52 | 53 | /// 54 | /// 在事务中执行 55 | /// 56 | /// 57 | Task ExecuteInTransactionAsync(); 58 | #endregion 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/Services/SubUserService.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Overt.User.Application.Constracts; 3 | using Overt.User.Application.Models; 4 | using Overt.User.Domain.Contracts; 5 | using Overt.User.Domain.Entities; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Transactions; 12 | 13 | namespace Overt.User.Application.Services 14 | { 15 | public class SubUserService : ISubUserService 16 | { 17 | IMapper _mapper; 18 | ISubUserRepository _repository; 19 | public SubUserService( 20 | IMapper mapper, 21 | ISubUserRepository repository) 22 | { 23 | _mapper = mapper; 24 | _repository = repository; 25 | } 26 | 27 | public async Task AddAsync(UserPostModel model) 28 | { 29 | if (!model.IsValid(out Exception ex)) 30 | throw ex; 31 | 32 | // 分表标识赋值 33 | _repository.AddTime = DateTime.Now; 34 | 35 | var entity = _mapper.Map(model); 36 | entity.AddTime = DateTime.Now; 37 | var result = await _repository.AddAsync(entity, true); 38 | if (!result) 39 | throw new Exception($"新增失败"); 40 | return entity.UserId; 41 | } 42 | 43 | public async Task GetAsync(int userId, bool isMaster = false) 44 | { 45 | if (userId <= 0) 46 | throw new Exception($"UserId必须大于0"); 47 | 48 | // 分表标识赋值 49 | _repository.AddTime = DateTime.Now; 50 | var entity = await _repository.GetAsync(oo => oo.UserId == userId, isMaster: isMaster); 51 | return _mapper.Map(entity); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/SqlExpression/Resolve/NewSqlExpression.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | using System.Reflection; 3 | 4 | namespace Overt.Core.Data.Expressions 5 | { 6 | class NewSqlExpression : BaseSqlExpression 7 | { 8 | protected override SqlGenerate Update(NewExpression expression, SqlGenerate sqlGenerate) 9 | { 10 | for (int i = 0; i < expression.Members.Count; i++) 11 | { 12 | var m = expression.Members[i]; 13 | sqlGenerate += $"{m.Name.ParamSql(sqlGenerate)} = "; 14 | 15 | var val = SqlExpressionCompiler.Evaluate(expression.Arguments[i]); 16 | sqlGenerate.AddDbParameter(val); 17 | sqlGenerate += ","; 18 | } 19 | if (sqlGenerate[sqlGenerate.Length - 1] == ',') 20 | sqlGenerate.Sql.Remove(sqlGenerate.Length - 1, 1); 21 | 22 | return sqlGenerate; 23 | } 24 | 25 | protected override SqlGenerate Select(NewExpression expression, SqlGenerate sqlGenerate) 26 | { 27 | foreach (Expression item in expression.Arguments) 28 | { 29 | SqlExpressionProvider.Select(item, sqlGenerate); 30 | } 31 | return sqlGenerate; 32 | } 33 | 34 | protected override SqlGenerate OrderBy(NewExpression expression, SqlGenerate sqlGenerate) 35 | { 36 | foreach (Expression item in expression.Arguments) 37 | { 38 | SqlExpressionProvider.OrderBy(item, sqlGenerate); 39 | sqlGenerate += ","; 40 | } 41 | if (sqlGenerate[sqlGenerate.Length - 1] == ',') 42 | sqlGenerate.Sql.Remove(sqlGenerate.Length - 1, 1); 43 | 44 | return sqlGenerate; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/SqlExpression/SqlExpressionCompiler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using static Overt.Core.Data.Expressions.SqlExpressionFingerprint; 4 | 5 | namespace Overt.Core.Data.Expressions 6 | { 7 | /// 8 | /// 参数编译器 9 | /// base ServiceStack 10 | /// 11 | public static class SqlExpressionCompiler 12 | { 13 | private static readonly ParameterExpression _unusedParameterExpr = Expression.Parameter(typeof(object), "_unused"); 14 | 15 | /// 16 | /// 编译 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | public static Func Compile(this Expression> lambdaExpression) 23 | { 24 | if (lambdaExpression == null) 25 | throw new ArgumentNullException(nameof(lambdaExpression)); 26 | 27 | return ExpressionCompiler.Process(lambdaExpression); 28 | } 29 | /// 30 | /// 编译 31 | /// 32 | /// 33 | /// 34 | public static object Evaluate(Expression arg) 35 | { 36 | if (arg == null) 37 | throw new ArgumentNullException(nameof(arg)); 38 | 39 | var func = Wrap(arg); 40 | return func(null); 41 | } 42 | 43 | private static Func Wrap(Expression arg) 44 | { 45 | var lambdaExpr = Expression.Lambda>(Expression.Convert(arg, typeof(object)), _unusedParameterExpr); 46 | return ExpressionCompiler.Process(lambdaExpr); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/Overt.Core.Data/Params/OrderByField.cs: -------------------------------------------------------------------------------- 1 | namespace Overt.Core.Data 2 | { 3 | /// 4 | /// 排序字段对象 5 | /// 6 | public class OrderByField 7 | { 8 | /// 9 | /// 字段 使用nameof(Class.Property) 10 | /// 11 | public string Field { get; set; } 12 | /// 13 | /// 排序类型 14 | /// 15 | public FieldSortType OrderBy { get; set; } 16 | /// 17 | /// 构造函数 18 | /// 19 | /// 20 | /// 21 | public OrderByField(string field, FieldSortType orderBy = FieldSortType.Asc) 22 | { 23 | Field = field; 24 | OrderBy = orderBy; 25 | } 26 | 27 | /// 28 | /// 静态构造对象 29 | /// 30 | /// 31 | /// 32 | /// 33 | public static OrderByField Create(string field, FieldSortType orderBy = FieldSortType.Asc) 34 | { 35 | return new OrderByField(field, orderBy); 36 | } 37 | } 38 | 39 | /// 40 | /// 扩展类 41 | /// 42 | public static class OrderByFieldExtension 43 | { 44 | /// 45 | /// 顺序构造对象扩展方法 46 | /// 47 | /// 48 | /// 49 | public static OrderByField OrderBy(this string field) 50 | { 51 | return new OrderByField(field, FieldSortType.Asc); 52 | } 53 | 54 | /// 55 | /// 倒序构造对象扩展方法 56 | /// 57 | /// 58 | /// 59 | public static OrderByField OrderByDesc(this string field) 60 | { 61 | return new OrderByField(field, FieldSortType.Desc); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/Extensions/ModelValidationExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.Linq; 4 | 5 | namespace Overt.User.Application 6 | { 7 | public static class ModelValidationExtensions 8 | { 9 | public static bool IsValid(this object obj,out Exception exception) 10 | { 11 | exception = null; 12 | 13 | if(obj == null) 14 | { 15 | exception = new ArgumentNullException(); 16 | return false; 17 | } 18 | 19 | var context = new ValidationContext(obj); 20 | var result = Validate(context); 21 | if (result == null) 22 | return true; 23 | 24 | exception = new Exception(result.ErrorMessage); 25 | return false; 26 | } 27 | 28 | private static ValidationResult Validate(ValidationContext context) 29 | { 30 | var properties = context.ObjectType.GetProperties(); 31 | 32 | if (context.ObjectInstance is IValidatableObject) 33 | { 34 | IValidatableObject valid = (IValidatableObject)context.ObjectInstance; 35 | var validationResults = valid.Validate(context); 36 | if (validationResults != null && validationResults.Count() > 0) 37 | { 38 | return valid.Validate(context).FirstOrDefault(); 39 | } 40 | } 41 | 42 | foreach (var property in properties) 43 | { 44 | var validationAttributes = property.GetCustomAttributes(false).OfType(); 45 | foreach (var attribute in validationAttributes) 46 | { 47 | bool isValid = attribute.IsValid(property.GetValue(context.ObjectInstance)); 48 | if (!isValid) 49 | { 50 | return new ValidationResult(attribute.ErrorMessage, new[] { property.Name }); 51 | } 52 | } 53 | } 54 | 55 | return null; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/Extensions/ModelValidationExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.Linq; 4 | 5 | namespace Overt.User.Application 6 | { 7 | public static class ModelValidationExtensions 8 | { 9 | public static bool IsValid(this object obj,out Exception exception) 10 | { 11 | exception = null; 12 | 13 | if(obj == null) 14 | { 15 | exception = new ArgumentNullException(); 16 | return false; 17 | } 18 | 19 | var context = new ValidationContext(obj); 20 | var result = Validate(context); 21 | if (result == null) 22 | return true; 23 | 24 | exception = new Exception(result.ErrorMessage); 25 | return false; 26 | } 27 | 28 | private static ValidationResult Validate(ValidationContext context) 29 | { 30 | var properties = context.ObjectType.GetProperties(); 31 | 32 | if (context.ObjectInstance is IValidatableObject) 33 | { 34 | IValidatableObject valid = (IValidatableObject)context.ObjectInstance; 35 | var validationResults = valid.Validate(context); 36 | if (validationResults != null && validationResults.Count() > 0) 37 | { 38 | return valid.Validate(context).FirstOrDefault(); 39 | } 40 | } 41 | 42 | foreach (var property in properties) 43 | { 44 | var validationAttributes = property.GetCustomAttributes(false).OfType(); 45 | foreach (var attribute in validationAttributes) 46 | { 47 | bool isValid = attribute.IsValid(property.GetValue(context.ObjectInstance)); 48 | if (!isValid) 49 | { 50 | return new ValidationResult(attribute.ErrorMessage, new[] { property.Name }); 51 | } 52 | } 53 | } 54 | 55 | return null; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/core/Overt.Core.Test/ApplicationTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using Overt.User.Application.Constracts; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using System.Threading.Tasks; 5 | using System.Collections.Generic; 6 | 7 | namespace Overt.Core.Test 8 | { 9 | [TestClass] 10 | public class ApplicationTest : BaseTest 11 | { 12 | public ApplicationTest() : base() 13 | { 14 | } 15 | 16 | [TestMethod] 17 | public void DoSomethingTest() 18 | { 19 | var _userService = provider.GetService(); 20 | //_userService.DoSomethingWithTrans(); 21 | 22 | _userService.GetList(); 23 | 24 | //Parallel.For(0, 100, (i) => 25 | //{ 26 | // if (i % 2 == 0) 27 | // { 28 | // System.Diagnostics.Debug.WriteLine("Add: " + i); 29 | // var _userService = provider.GetService(); 30 | // _userService.Add(); 31 | // } 32 | // else 33 | // { 34 | // System.Diagnostics.Debug.WriteLine("GetList: " + i); 35 | // var _userService = provider.GetService(); 36 | // _userService.GetList(); 37 | // } 38 | //}); 39 | 40 | //var tasks = new List(); 41 | //for (int i = 0; i < 2; i++) 42 | //{ 43 | // var task = Task.Run(() => 44 | // { 45 | // var _userService = provider.GetService(); 46 | // _userService.DoSomethingWithTrans(); 47 | // }); 48 | // tasks.Add(task); 49 | //} 50 | //Task.WaitAll(tasks.ToArray()); 51 | } 52 | 53 | [TestMethod] 54 | public void DoSomeTest() 55 | { 56 | var _userService = provider.GetService(); 57 | _userService.DoSomethingWithTrans(); 58 | } 59 | 60 | 61 | 62 | [TestMethod] 63 | public void GetByIdsTest() 64 | { 65 | var _userService = provider.GetService(); 66 | _userService.GetByIds(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/Services/SubDbUserService.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Overt.User.Application.Constracts; 3 | using Overt.User.Application.Models; 4 | using Overt.User.Domain.Contracts; 5 | using Overt.User.Domain.Entities; 6 | using System; 7 | using System.Threading.Tasks; 8 | 9 | namespace Overt.User.Application.Services 10 | { 11 | public class SubDbUserService : ISubDbUserService 12 | { 13 | IMapper _mapper; 14 | ISubDbUserRepository _repository; 15 | public SubDbUserService( 16 | IMapper mapper, 17 | ISubDbUserRepository repository) 18 | { 19 | _mapper = mapper; 20 | _repository = repository; 21 | } 22 | 23 | public int Add(UserPostModel model) 24 | { 25 | if (!model.IsValid(out Exception ex)) 26 | throw ex; 27 | 28 | var entity = _mapper.Map(model); 29 | entity.AddTime = DateTime.Now; 30 | var result = _repository.Add(entity, true); 31 | if (!result) 32 | throw new Exception($"新增失败"); 33 | return entity.UserId; 34 | } 35 | 36 | public UserModel Get(int userId, bool isMaster = false) 37 | { 38 | if (userId <= 0) 39 | throw new Exception($"UserId必须大于0"); 40 | 41 | var entity = _repository.Get(oo => oo.UserId == userId, isMaster: isMaster); 42 | return _mapper.Map(entity); 43 | } 44 | 45 | public async Task AddAsync(UserPostModel model) 46 | { 47 | if (!model.IsValid(out Exception ex)) 48 | throw ex; 49 | 50 | var entity = _mapper.Map(model); 51 | entity.AddTime = DateTime.Now; 52 | var result = await _repository.AddAsync(entity, true); 53 | if (!result) 54 | throw new Exception($"新增失败"); 55 | return entity.UserId; 56 | } 57 | 58 | public async Task GetAsync(int userId, bool isMaster = false) 59 | { 60 | if (userId <= 0) 61 | throw new Exception($"UserId必须大于0"); 62 | 63 | var entity = await _repository.GetAsync(oo => oo.UserId == userId, isMaster: isMaster); 64 | return _mapper.Map(entity); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Extensions/Table.Extensions.cs: -------------------------------------------------------------------------------- 1 | using Dapper; 2 | using System; 3 | using System.Collections.Concurrent; 4 | using System.Transactions; 5 | 6 | namespace Overt.Core.Data 7 | { 8 | /// 9 | /// 表管理 10 | /// 11 | public static class TableExtensions 12 | { 13 | private static ConcurrentDictionary lockObjectMap = new ConcurrentDictionary(); 14 | private static ConcurrentDictionary tableExistMap = new ConcurrentDictionary(); 15 | 16 | /// 17 | /// 检查表是否存在 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// false, 直接返回默认数据即可 23 | public static bool CheckTableIfMissingCreate(this IBaseRepository repository, bool isMaster) 24 | where T : class, new() 25 | { 26 | var tableName = repository.TableNameFunc?.Invoke(); 27 | var createScript = repository.CreateScriptFunc?.Invoke(tableName); 28 | if (string.IsNullOrEmpty(createScript)) 29 | return true; 30 | if (string.IsNullOrEmpty(tableName)) 31 | throw new Exception($"CheckTableIfMissingCreate: TableNameFunc 必须提供"); 32 | 33 | var tableKey = $"{repository.DbStoreKey}_{tableName}_{isMaster}"; 34 | lock (lockObjectMap.GetOrAdd(tableKey, new object())) 35 | { 36 | var existTable = tableExistMap.GetOrAdd(tableKey, k => repository.IsExistTable(tableName, isMaster)); 37 | if (existTable) 38 | return true; 39 | 40 | tableExistMap.TryRemove(tableKey, out existTable); 41 | if (!isMaster) 42 | return false; 43 | 44 | try 45 | { 46 | using (var scope = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled)) 47 | using (var connection = repository.OpenConnection(true)) 48 | { 49 | connection.Execute(createScript); 50 | } 51 | return true; 52 | } 53 | catch (Exception ex) 54 | { 55 | throw ex; 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Overt.Core.Data.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net461;netstandard2.0 5 | Overt.Core.Data 6 | 7 | Yaofeng 8 | Overt.Core.Data 9 | false 10 | lambda表达式解析增加 !Contains 生成 not like 11 | Overt 12 | 13 | true 14 | 1.0.0.0 15 | 1.0.0.0 16 | 2.3.3 17 | http://github.com/overtly/core-data 18 | 19 | 20 | 21 | Overt.Core.Data.xml 22 | 23 | 24 | 25 | bin\Release\netstandard2.0\Overt.Core.Data.xml 26 | 27 | 28 | 29 | TRACE;DEBUG;NET461 30 | 31 | 32 | 33 | ASP.NET Core 2 integration for Overt.Core.Data - .NET Standard 2 34 | $(DefineConstants);ASP_NET_CORE;ASP_NET_CORE2 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/Services/SubDbUser2Service.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Overt.User.Application.Constracts; 3 | using Overt.User.Application.Models; 4 | using Overt.User.Domain.Contracts; 5 | using Overt.User.Domain.Entities; 6 | using System; 7 | using System.Threading.Tasks; 8 | 9 | namespace Overt.User.Application.Services 10 | { 11 | public class SubDbUser2Service : ISubDbUser2Service 12 | { 13 | IMapper _mapper; 14 | ISubDbUser2Repository _repository; 15 | public SubDbUser2Service( 16 | IMapper mapper, 17 | ISubDbUser2Repository repository) 18 | { 19 | _mapper = mapper; 20 | _repository = repository; 21 | } 22 | 23 | public int Add(UserPostModel model) 24 | { 25 | if (!model.IsValid(out Exception ex)) 26 | throw ex; 27 | 28 | _repository.SubDbAddTime = DateTime.Now; 29 | var entity = _mapper.Map(model); 30 | entity.AddTime = DateTime.Now; 31 | var result = _repository.Add(entity, true); 32 | if (!result) 33 | throw new Exception($"新增失败"); 34 | return entity.UserId; 35 | } 36 | 37 | public UserModel Get(int userId, bool isMaster = false) 38 | { 39 | if (userId <= 0) 40 | throw new Exception($"UserId必须大于0"); 41 | 42 | _repository.SubDbAddTime = DateTime.Now; 43 | var entity = _repository.Get(oo => oo.UserId == userId, isMaster: isMaster); 44 | return _mapper.Map(entity); 45 | } 46 | 47 | public async Task AddAsync(UserPostModel model) 48 | { 49 | if (!model.IsValid(out Exception ex)) 50 | throw ex; 51 | 52 | _repository.SubDbAddTime = DateTime.Now; 53 | var entity = _mapper.Map(model); 54 | entity.AddTime = DateTime.Now; 55 | var result = await _repository.AddAsync(entity, true); 56 | if (!result) 57 | throw new Exception($"新增失败"); 58 | return entity.UserId; 59 | } 60 | 61 | public async Task GetAsync(int userId, bool isMaster = false) 62 | { 63 | if (userId <= 0) 64 | throw new Exception($"UserId必须大于0"); 65 | 66 | _repository.SubDbAddTime = DateTime.Now; 67 | var entity = await _repository.GetAsync(oo => oo.UserId == userId, isMaster: isMaster); 68 | return _mapper.Map(entity); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/Services/SubDbUser2Service.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Overt.User.Application.Constracts; 3 | using Overt.User.Application.Models; 4 | using Overt.User.Domain.Contracts; 5 | using Overt.User.Domain.Entities; 6 | using System; 7 | using System.Threading.Tasks; 8 | 9 | namespace Overt.User.Application.Services 10 | { 11 | public class SubDbUser2Service : ISubDbUser2Service 12 | { 13 | IMapper _mapper; 14 | ISubDbUser2Repository _repository; 15 | public SubDbUser2Service( 16 | IMapper mapper, 17 | ISubDbUser2Repository repository) 18 | { 19 | _mapper = mapper; 20 | _repository = repository; 21 | } 22 | 23 | public int Add(UserPostModel model) 24 | { 25 | if (!model.IsValid(out Exception ex)) 26 | throw ex; 27 | 28 | _repository.SubDbAddTime = DateTime.Now; 29 | var entity = _mapper.Map(model); 30 | entity.AddTime = DateTime.Now; 31 | var result = _repository.Add(entity, true); 32 | if (!result) 33 | throw new Exception($"新增失败"); 34 | return entity.UserId; 35 | } 36 | 37 | public UserModel Get(int userId, bool isMaster = false) 38 | { 39 | if (userId <= 0) 40 | throw new Exception($"UserId必须大于0"); 41 | 42 | _repository.SubDbAddTime = DateTime.Now; 43 | var entity = _repository.Get(oo => oo.UserId == userId, isMaster: isMaster); 44 | return _mapper.Map(entity); 45 | } 46 | 47 | public async Task AddAsync(UserPostModel model) 48 | { 49 | if (!model.IsValid(out Exception ex)) 50 | throw ex; 51 | 52 | _repository.SubDbAddTime = DateTime.Now; 53 | var entity = _mapper.Map(model); 54 | entity.AddTime = DateTime.Now; 55 | var result = await _repository.AddAsync(entity, true); 56 | if (!result) 57 | throw new Exception($"新增失败"); 58 | return entity.UserId; 59 | } 60 | 61 | public async Task GetAsync(int userId, bool isMaster = false) 62 | { 63 | if (userId <= 0) 64 | throw new Exception($"UserId必须大于0"); 65 | 66 | _repository.SubDbAddTime = DateTime.Now; 67 | var entity = await _repository.GetAsync(oo => oo.UserId == userId, isMaster: isMaster); 68 | return _mapper.Map(entity); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/net46/Overt.Core.DataConsole/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/Services/SubUserService.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Overt.User.Application.Constracts; 3 | using Overt.User.Application.Models; 4 | using Overt.User.Domain.Contracts; 5 | using Overt.User.Domain.Entities; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Transactions; 12 | 13 | namespace Overt.User.Application.Services 14 | { 15 | public class SubUserService : ISubUserService 16 | { 17 | IMapper _mapper; 18 | ISubUserRepository _repository; 19 | public SubUserService( 20 | IMapper mapper, 21 | ISubUserRepository repository) 22 | { 23 | _mapper = mapper; 24 | _repository = repository; 25 | } 26 | public int Add(UserPostModel model) 27 | { 28 | if (!model.IsValid(out Exception ex)) 29 | throw ex; 30 | 31 | // 分表标识赋值 32 | _repository.AddTime = DateTime.Now; 33 | 34 | var entity = _mapper.Map(model); 35 | entity.AddTime = DateTime.Now; 36 | var result = _repository.Add(entity, true); 37 | if (!result) 38 | throw new Exception($"新增失败"); 39 | return entity.UserId; 40 | } 41 | 42 | public UserModel Get(int userId, bool isMaster = false) 43 | { 44 | if (userId <= 0) 45 | throw new Exception($"UserId必须大于0"); 46 | 47 | // 分表标识赋值 48 | _repository.AddTime = DateTime.Now; 49 | var entity = _repository.Get(oo => oo.UserId == userId, isMaster: isMaster); 50 | return _mapper.Map(entity); 51 | } 52 | 53 | public async Task AddAsync(UserPostModel model) 54 | { 55 | if (!model.IsValid(out Exception ex)) 56 | throw ex; 57 | 58 | // 分表标识赋值 59 | _repository.AddTime = DateTime.Now; 60 | 61 | var entity = _mapper.Map(model); 62 | entity.AddTime = DateTime.Now; 63 | var result = await _repository.AddAsync(entity, true); 64 | if (!result) 65 | throw new Exception($"新增失败"); 66 | return entity.UserId; 67 | } 68 | 69 | public async Task GetAsync(int userId, bool isMaster = false) 70 | { 71 | if (userId <= 0) 72 | throw new Exception($"UserId必须大于0"); 73 | 74 | // 分表标识赋值 75 | _repository.AddTime = DateTime.Now; 76 | var entity = await _repository.GetAsync(oo => oo.UserId == userId, isMaster: isMaster); 77 | return _mapper.Map(entity); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/SqlExpression/Resolve/UnarySqlExpression.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | 3 | namespace Overt.Core.Data.Expressions 4 | { 5 | class UnarySqlExpression : BaseSqlExpression 6 | { 7 | protected override SqlGenerate Select(UnaryExpression expression, SqlGenerate sqlGenerate) 8 | { 9 | SqlExpressionProvider.Select(expression.Operand, sqlGenerate); 10 | return sqlGenerate; 11 | } 12 | 13 | protected override SqlGenerate Where(UnaryExpression expression, SqlGenerate sqlGenerate) 14 | { 15 | SqlExpressionProvider.Where(expression.Operand, sqlGenerate); 16 | switch (expression.NodeType) 17 | { 18 | case ExpressionType.Not: 19 | if (expression.Operand is MethodCallExpression) 20 | { 21 | if (IsStaticArrayMethod(expression.Operand as MethodCallExpression) || 22 | IsEnumerableMethod(expression.Operand as MethodCallExpression)) 23 | { 24 | sqlGenerate.RelaceLast("in", "not in"); 25 | } 26 | else 27 | { 28 | sqlGenerate.RelaceLast("like", "not like"); 29 | } 30 | } 31 | else 32 | sqlGenerate += " = 0"; 33 | break; 34 | } 35 | 36 | return sqlGenerate; 37 | } 38 | 39 | protected override SqlGenerate OrderBy(UnaryExpression expression, SqlGenerate sqlGenerate) 40 | { 41 | SqlExpressionProvider.OrderBy(expression.Operand, sqlGenerate); 42 | return sqlGenerate; 43 | } 44 | 45 | protected override SqlGenerate Max(UnaryExpression expression, SqlGenerate sqlGenerate) 46 | { 47 | SqlExpressionProvider.Max(expression.Operand, sqlGenerate); 48 | return sqlGenerate; 49 | } 50 | 51 | protected override SqlGenerate Min(UnaryExpression expression, SqlGenerate sqlGenerate) 52 | { 53 | SqlExpressionProvider.Min(expression.Operand, sqlGenerate); 54 | return sqlGenerate; 55 | } 56 | 57 | protected override SqlGenerate Avg(UnaryExpression expression, SqlGenerate sqlGenerate) 58 | { 59 | SqlExpressionProvider.Avg(expression.Operand, sqlGenerate); 60 | return sqlGenerate; 61 | } 62 | 63 | protected override SqlGenerate Count(UnaryExpression expression, SqlGenerate sqlGenerate) 64 | { 65 | SqlExpressionProvider.Count(expression.Operand, sqlGenerate); 66 | return sqlGenerate; 67 | } 68 | 69 | protected override SqlGenerate Sum(UnaryExpression expression, SqlGenerate sqlGenerate) 70 | { 71 | SqlExpressionProvider.Sum(expression.Operand, sqlGenerate); 72 | return sqlGenerate; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/SqlExpression/Resolve/Basic/ISqlExpression.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | 3 | namespace Overt.Core.Data.Expressions 4 | { 5 | /// 6 | /// interface 7 | /// 8 | public interface ISqlExpression 9 | { 10 | /// 11 | /// Update 12 | /// 13 | /// 14 | /// 15 | /// 16 | SqlGenerate Update(Expression expression, SqlGenerate sqlGenerate); 17 | /// 18 | /// Select 19 | /// 20 | /// 21 | /// 22 | /// 23 | SqlGenerate Select(Expression expression, SqlGenerate sqlGenerate); 24 | /// 25 | /// Where 26 | /// 27 | /// 28 | /// 29 | /// 30 | SqlGenerate Where(Expression expression, SqlGenerate sqlGenerate); 31 | /// 32 | /// In 33 | /// 34 | /// 35 | /// 36 | /// 37 | SqlGenerate In(Expression expression, SqlGenerate sqlGenerate); 38 | /// 39 | /// OrderBy 40 | /// 41 | /// 42 | /// 43 | /// 44 | SqlGenerate OrderBy(Expression expression, SqlGenerate sqlGenerate); 45 | /// 46 | /// Max 47 | /// 48 | /// 49 | /// 50 | /// 51 | SqlGenerate Max(Expression expression, SqlGenerate sqlGenerate); 52 | /// 53 | /// Min 54 | /// 55 | /// 56 | /// 57 | /// 58 | SqlGenerate Min(Expression expression, SqlGenerate sqlGenerate); 59 | /// 60 | /// Avg 61 | /// 62 | /// 63 | /// 64 | /// 65 | SqlGenerate Avg(Expression expression, SqlGenerate sqlGenerate); 66 | /// 67 | /// Count 68 | /// 69 | /// 70 | /// 71 | /// 72 | SqlGenerate Count(Expression expression, SqlGenerate sqlGenerate); 73 | /// 74 | /// Sum 75 | /// 76 | /// 77 | /// 78 | /// 79 | SqlGenerate Sum(Expression expression, SqlGenerate sqlGenerate); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Repository/PropertyAssist.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | #if ASP_NET_CORE 4 | using Microsoft.Extensions.Configuration; 5 | #else 6 | using System.Configuration; 7 | #endif 8 | 9 | namespace Overt.Core.Data 10 | { 11 | /// 12 | /// DbRespository 抽象类 13 | /// 14 | public abstract class PropertyAssist : IPropertyAssist 15 | { 16 | #region Private Property 17 | #if ASP_NET_CORE 18 | private readonly IConfiguration _configuration; 19 | #endif 20 | #endregion 21 | 22 | #region Constructor 23 | #if ASP_NET_CORE 24 | /// 25 | /// 实例化 26 | /// 27 | /// 配置注入 28 | /// 数据库前缀 29 | public PropertyAssist(IConfiguration configuration, string dbStoreKey = "") 30 | { 31 | _configuration = configuration; 32 | DbStoreKey = dbStoreKey; 33 | } 34 | #else 35 | /// 36 | /// 实例化 37 | /// 38 | /// 数据库前缀 39 | public PropertyAssist(string dbStoreKey = "") 40 | { 41 | DbStoreKey = dbStoreKey; 42 | } 43 | #endif 44 | #endregion 45 | 46 | #region Public Method 47 | /// 48 | /// 数据库名key 49 | /// 50 | public string DbStoreKey { get; set; } 51 | 52 | /// 53 | /// 打开连接 已赋值 connection 属性 54 | /// 55 | /// 56 | public virtual IDbConnection OpenConnection(bool isMaster = false) 57 | { 58 | IDbConnection connection; 59 | 60 | #if ASP_NET_CORE 61 | connection = new DataContext(_configuration, isMaster, DbStoreKey, ConnectionFunc).DbConnection; 62 | #else 63 | connection = new DataContext(isMaster, DbStoreKey, ConnectionFunc).DbConnection; 64 | #endif 65 | 66 | if (connection == null) 67 | throw new Exception("数据库连接创建失败,请检查连接字符串是否正确..."); 68 | 69 | if (connection.State != ConnectionState.Open) 70 | connection.Open(); 71 | 72 | return connection; 73 | } 74 | 75 | /// 76 | /// 数据库连接方法 77 | /// 78 | #if ASP_NET_CORE 79 | public virtual Func ConnectionFunc { get; set; } 80 | #else 81 | public virtual Func ConnectionFunc { get; set; } 82 | #endif 83 | 84 | /// 85 | /// 表名方法 86 | /// 87 | public virtual Func TableNameFunc { get; set; } 88 | 89 | /// 90 | /// 创建表的脚本 91 | /// 92 | public virtual Func CreateScriptFunc { get; set; } 93 | 94 | /// 95 | /// 执行的sql脚本 96 | /// 97 | public virtual string ExecuteScript { get; set; } 98 | #endregion 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/SqlExpression/Resolve/LambdaSqlExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using System.Text; 5 | 6 | namespace Overt.Core.Data.Expressions 7 | { 8 | public class LambdaSqlExpression : BaseSqlExpression 9 | { 10 | protected override SqlGenerate Update(LambdaExpression expression, SqlGenerate sqlGenerate) 11 | { 12 | SqlExpressionProvider.Update(expression.Body, sqlGenerate); 13 | return sqlGenerate; 14 | } 15 | protected override SqlGenerate Select(LambdaExpression expression, SqlGenerate sqlGenerate) 16 | { 17 | SqlExpressionProvider.Select(expression.Body, sqlGenerate); 18 | return sqlGenerate; 19 | } 20 | protected override SqlGenerate Where(LambdaExpression expression, SqlGenerate sqlGenerate) 21 | { 22 | if (expression.Body.NodeType == ExpressionType.MemberAccess) 23 | { 24 | var memberExpression = expression.Body as MemberExpression; 25 | if (memberExpression.Expression == null) 26 | return sqlGenerate; 27 | 28 | //添加属性 29 | SqlExpressionProvider.Where(memberExpression, sqlGenerate); 30 | 31 | if (memberExpression.Expression.Type.IsNullableType()) 32 | return sqlGenerate; 33 | 34 | sqlGenerate += " = 1"; 35 | return sqlGenerate; 36 | } 37 | 38 | SqlExpressionProvider.Where(expression.Body, sqlGenerate); 39 | return sqlGenerate; 40 | } 41 | protected override SqlGenerate In(LambdaExpression expression, SqlGenerate sqlGenerate) 42 | { 43 | SqlExpressionProvider.In(expression.Body, sqlGenerate); 44 | return sqlGenerate; 45 | } 46 | protected override SqlGenerate OrderBy(LambdaExpression expression, SqlGenerate sqlGenerate) 47 | { 48 | SqlExpressionProvider.OrderBy(expression.Body, sqlGenerate); 49 | return sqlGenerate; 50 | } 51 | protected override SqlGenerate Max(LambdaExpression expression, SqlGenerate sqlGenerate) 52 | { 53 | SqlExpressionProvider.Max(expression.Body, sqlGenerate); 54 | return sqlGenerate; 55 | } 56 | protected override SqlGenerate Min(LambdaExpression expression, SqlGenerate sqlGenerate) 57 | { 58 | SqlExpressionProvider.Min(expression.Body, sqlGenerate); 59 | return sqlGenerate; 60 | } 61 | protected override SqlGenerate Avg(LambdaExpression expression, SqlGenerate sqlGenerate) 62 | { 63 | SqlExpressionProvider.Avg(expression.Body, sqlGenerate); 64 | return sqlGenerate; 65 | } 66 | protected override SqlGenerate Count(LambdaExpression expression, SqlGenerate sqlGenerate) 67 | { 68 | SqlExpressionProvider.Count(expression.Body, sqlGenerate); 69 | return sqlGenerate; 70 | } 71 | protected override SqlGenerate Sum(LambdaExpression expression, SqlGenerate sqlGenerate) 72 | { 73 | SqlExpressionProvider.Sum(expression.Body, sqlGenerate); 74 | return sqlGenerate; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/ExpressionHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq.Expressions; 3 | 4 | namespace Overt.Core.Data.Expressions 5 | { 6 | /// 7 | /// 解析为 Dictionary 获取表达式中的key - value 8 | /// 只需要有等于号的 9 | /// 10 | internal class ExpressionHelper 11 | { 12 | /// 13 | /// 获取参数 14 | /// 15 | /// 16 | /// 17 | public static void Resolve(Expression expression, ref Dictionary dictionary) 18 | { 19 | if (expression == null) 20 | return; 21 | 22 | if (expression is BinaryExpression) 23 | { 24 | var binaryExpression = ((BinaryExpression)expression); 25 | ResolveBinary(binaryExpression, ref dictionary); 26 | } 27 | } 28 | 29 | #region Binary 30 | private static void ResolveBinary(BinaryExpression expression, ref Dictionary dictionary) 31 | { 32 | object left = null, right = null; 33 | if (expression.NodeType == ExpressionType.AndAlso || expression.NodeType == ExpressionType.OrElse) 34 | { 35 | if (expression.Left.IsBooleanComparison()) 36 | left = ResolveMemberOrConstant(expression.Left); 37 | else 38 | Resolve(expression.Left, ref dictionary); 39 | 40 | if (expression.Right.IsBooleanComparison()) 41 | right = ResolveMemberOrConstant(expression.Right); 42 | else 43 | Resolve(expression.Right, ref dictionary); 44 | } 45 | else if (expression.NodeType == ExpressionType.Equal) 46 | { 47 | left = ResolveMemberOrConstant(expression.Left); 48 | right = ResolveMemberOrConstant(expression.Right); 49 | } 50 | 51 | if (left != null && !dictionary.ContainsKey(left)) 52 | { 53 | dictionary.Add(left, right); 54 | } 55 | } 56 | #endregion 57 | 58 | #region Member / Constant 59 | private static object ResolveMemberOrConstant(Expression expression) 60 | { 61 | if (expression == null) 62 | return null; 63 | 64 | if (expression is MemberExpression) 65 | return ResolveMember((MemberExpression)expression); 66 | if (expression is ConstantExpression) 67 | return ResolveConstant((ConstantExpression)expression); 68 | return null; 69 | } 70 | 71 | private static object ResolveMember(MemberExpression expression) 72 | { 73 | if (expression.Expression != null) 74 | { 75 | if (expression.Member.DeclaringType.IsNullableType()) 76 | return null; 77 | 78 | if (expression.IsParameterOrConvertAccess()) 79 | return expression.Member.Name; 80 | } 81 | 82 | var val = SqlExpressionCompiler.Evaluate(expression); 83 | return val; 84 | } 85 | 86 | private static object ResolveConstant(ConstantExpression expression) 87 | { 88 | return expression.Value; 89 | } 90 | #endregion 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Extensions/EntityDefinition.Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | 7 | namespace Overt.Core.Data 8 | { 9 | /// 10 | /// 字段定义说明 11 | /// 12 | public static class EntityDefinitionExtensions 13 | { 14 | private static ConcurrentDictionary> _cacheSubmeter = new ConcurrentDictionary>(); 15 | 16 | /// 17 | /// 18 | /// 19 | /// 属性 20 | /// 21 | /// 22 | internal static TAttribute GetAttribute(this Type entity) where TAttribute : Attribute 23 | { 24 | var attrs = entity.GetCustomAttributes(typeof(TAttribute)); 25 | if (attrs?.Count() > 0) 26 | return (TAttribute)attrs.First(); 27 | return null; 28 | } 29 | 30 | /// 31 | /// 32 | /// 33 | /// 属性 34 | /// 35 | /// 36 | internal static TAttribute GetAttribute(this PropertyInfo property) where TAttribute : Attribute 37 | { 38 | var obs = property.GetCustomAttributes(typeof(TAttribute), false); 39 | if (obs?.Count() > 0) 40 | return (TAttribute)obs.First(); 41 | return null; 42 | } 43 | 44 | /// 45 | /// 46 | /// 47 | /// 48 | /// 49 | /// 50 | internal static PropertyInfo GetProperty(this Type entity) where TAttribute : Attribute 51 | { 52 | var propertyInfos = _cacheSubmeter.GetOrAdd($"{entity.Name}_{typeof(TAttribute).Name}", 53 | key => entity.GetPropertyByAttribute()); 54 | return propertyInfos.FirstOrDefault(); 55 | } 56 | 57 | /// 58 | /// 59 | /// 60 | /// 61 | /// 62 | /// 63 | internal static List GetProperties(this Type entity) where TAttribute : Attribute 64 | { 65 | var propertyInfos = _cacheSubmeter.GetOrAdd($"{entity.Name}_{typeof(TAttribute).Name}", 66 | key => entity.GetPropertyByAttribute()); 67 | return propertyInfos; 68 | } 69 | 70 | /// 71 | /// 72 | /// 73 | /// 属性 74 | /// 75 | /// 76 | internal static List GetPropertyByAttribute(this Type entity) where TAttribute : Attribute 77 | { 78 | var list = new List(); 79 | var pis = entity.GetProperties(); 80 | foreach (var item in pis) 81 | { 82 | var obs = item.GetCustomAttributes(typeof(TAttribute), false); 83 | if (obs?.Count() > 0) 84 | list.Add(item); 85 | } 86 | return list; 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Domain/Overt.User.Domain.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F34F6B13-B939-47A3-827E-E7015FD1B434} 8 | Library 9 | Properties 10 | Overt.User.Domain 11 | Overt.User.Domain 12 | v4.6.2 13 | 512 14 | true 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | ..\..\..\packages\Autofac.4.8.1\lib\net45\Autofac.dll 37 | 38 | 39 | ..\..\..\packages\Dapper.1.50.2\lib\net451\Dapper.dll 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | {8b1b556f-1d2c-49d2-8cb9-f9d2c7080786} 71 | Overt.Core.Data 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/net46/Overt.Core.DataConsole/Program.cs: -------------------------------------------------------------------------------- 1 | using Overt.User.Application.Constracts; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Autofac; 8 | 9 | namespace Overt.Core.DataConsole 10 | { 11 | class Program 12 | { 13 | static void Main(string[] args) 14 | { 15 | // autofac 16 | AutofacContainer.Register(); 17 | 18 | #region 单表 19 | var _userService = AutofacContainer.Container.Resolve(); 20 | 21 | // 新增 22 | var userId = _userService.AddAsync(new User.Application.Models.UserPostModel() 23 | { 24 | UserName = "TEST1", 25 | RealName = "TEST1", 26 | Password = "123456", 27 | IsSex = false, 28 | JsonValue = "{}" 29 | }).Result; 30 | 31 | // 修改 32 | var setResult = _userService.UpdateAsync(userId, true).Result; 33 | 34 | // 单条查询 35 | var getResult = _userService.GetAsync(userId).Result; 36 | 37 | // 多条查询 38 | var listResult = _userService.GetListAsync(new List() { userId }).Result; 39 | 40 | // 分页查询 41 | var pageResult = _userService.GetPageAsync(new User.Application.Models.UserSearchModel() 42 | { 43 | Page = 1, 44 | Size = 10, 45 | UserIds = new List { userId } 46 | }).Result; 47 | 48 | // 自定义SQL 49 | var otherResult = _userService.OtherSqlAsync().Result; 50 | 51 | // 删除 52 | var delResult = _userService.DeleteAsync(userId).Result; 53 | 54 | // ... 其他更多用法详见Readme,可有很多组合方式,并不局限于目前案例所示 55 | #endregion 56 | 57 | #region 分表 58 | var _subUserService = AutofacContainer.Container.Resolve(); 59 | 60 | // 添加 61 | var addResult1 = _subUserService.AddAsync(new User.Application.Models.UserPostModel() 62 | { 63 | UserName = "TEST_Sub", 64 | RealName = "TEST_Sub", 65 | Password = "123456", 66 | IsSex = false, 67 | JsonValue = "{}" 68 | }).Result; 69 | 70 | // 获取 71 | var getResult1 = _subUserService.GetAsync(addResult1).Result; 72 | #endregion 73 | 74 | #region 分库 75 | var _subDbUserService = AutofacContainer.Container.Resolve(); 76 | 77 | // 添加 78 | var addResult2 = _subDbUserService.AddAsync(new User.Application.Models.UserPostModel() 79 | { 80 | UserName = "TEST_SubDb", 81 | RealName = "TEST_SubDb", 82 | Password = "123456", 83 | IsSex = false, 84 | JsonValue = "{}" 85 | }).Result; 86 | 87 | // 获取 88 | var getResult2 = _subDbUserService.GetAsync(addResult2).Result; 89 | #endregion 90 | 91 | #region 分库2 92 | var _subDbUser2Service = AutofacContainer.Container.Resolve(); 93 | 94 | // 添加 95 | var addResult3 = _subDbUser2Service.AddAsync(new User.Application.Models.UserPostModel() 96 | { 97 | UserName = "TEST_SubDb", 98 | RealName = "TEST_SubDb", 99 | Password = "123456", 100 | IsSex = false, 101 | JsonValue = "{}" 102 | }).Result; 103 | 104 | // 获取 105 | var getResult3 = _subDbUser2Service.GetAsync(addResult3).Result; 106 | #endregion 107 | 108 | #region 事务 109 | var transResult = _userService.ExecuteInTransactionAsync().Result; 110 | #endregion 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/SqlExpression/Resolve/BinarySqlExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace Overt.Core.Data.Expressions 5 | { 6 | class BinarySqlExpression : BaseSqlExpression 7 | { 8 | private void OperatorParser(ExpressionType expressionNodeType, int operatorIndex, SqlGenerate sqlGenerate, bool useIs = false) 9 | { 10 | switch (expressionNodeType) 11 | { 12 | case ExpressionType.And: 13 | sqlGenerate.Sql.Insert(operatorIndex, " & "); 14 | break; 15 | case ExpressionType.AndAlso: 16 | sqlGenerate.Sql.Insert(operatorIndex, " and "); 17 | break; 18 | case ExpressionType.Equal: 19 | if (useIs) 20 | sqlGenerate.Sql.Insert(operatorIndex, " is "); 21 | else 22 | sqlGenerate.Sql.Insert(operatorIndex, " = "); 23 | break; 24 | case ExpressionType.GreaterThan: 25 | sqlGenerate.Sql.Insert(operatorIndex, " >"); 26 | break; 27 | case ExpressionType.GreaterThanOrEqual: 28 | sqlGenerate.Sql.Insert(operatorIndex, " >="); 29 | break; 30 | case ExpressionType.NotEqual: 31 | if (useIs) 32 | sqlGenerate.Sql.Insert(operatorIndex, " is not "); 33 | else 34 | sqlGenerate.Sql.Insert(operatorIndex, " <> "); 35 | break; 36 | case ExpressionType.Or: 37 | sqlGenerate.Sql.Insert(operatorIndex, " | "); 38 | break; 39 | case ExpressionType.OrElse: 40 | sqlGenerate.Sql.Insert(operatorIndex, " or "); 41 | break; 42 | case ExpressionType.LessThan: 43 | sqlGenerate.Sql.Insert(operatorIndex, " < "); 44 | break; 45 | case ExpressionType.LessThanOrEqual: 46 | sqlGenerate.Sql.Insert(operatorIndex, " <= "); 47 | break; 48 | default: 49 | throw new NotImplementedException("未实现的节点类型" + expressionNodeType); 50 | } 51 | } 52 | 53 | protected override SqlGenerate Where(BinaryExpression expression, SqlGenerate sqlGenerate) 54 | { 55 | int leftBracketIndex = -1, rightBracketIndex = -1, signIndex = -1, sqlLength = -1; 56 | 57 | leftBracketIndex = sqlGenerate.Length; 58 | 59 | #region 内部内容 60 | if (expression.NodeType == ExpressionType.AndAlso || expression.NodeType == ExpressionType.OrElse) 61 | { 62 | if (expression.Left.IsBooleanComparison()) 63 | { 64 | SqlExpressionProvider.Where(expression.Left, sqlGenerate); 65 | sqlGenerate += $" = 1"; 66 | } 67 | else 68 | { 69 | SqlExpressionProvider.Where(expression.Left, sqlGenerate); 70 | } 71 | signIndex = sqlGenerate.Length; 72 | 73 | 74 | if (expression.Right.IsBooleanComparison()) 75 | { 76 | SqlExpressionProvider.Where(expression.Right, sqlGenerate); 77 | sqlGenerate += $" = 1"; 78 | } 79 | else 80 | { 81 | SqlExpressionProvider.Where(expression.Right, sqlGenerate); 82 | } 83 | sqlLength = sqlGenerate.Length; 84 | } 85 | else 86 | { 87 | SqlExpressionProvider.Where(expression.Left, sqlGenerate); 88 | signIndex = sqlGenerate.Length; 89 | 90 | SqlExpressionProvider.Where(expression.Right, sqlGenerate); 91 | sqlLength = sqlGenerate.Length; 92 | } 93 | 94 | if (sqlLength - signIndex == 5 && sqlGenerate.ToString().EndsWith("null")) 95 | OperatorParser(expression.NodeType, signIndex, sqlGenerate, true); 96 | else 97 | OperatorParser(expression.NodeType, signIndex, sqlGenerate); 98 | #endregion 99 | 100 | if (expression.NodeType == ExpressionType.OrElse || expression.NodeType == ExpressionType.AndAlso || 101 | expression.NodeType == ExpressionType.Or || expression.NodeType == ExpressionType.And) 102 | { 103 | sqlGenerate.Sql.Insert(leftBracketIndex, " ( "); 104 | rightBracketIndex = sqlGenerate.Length; 105 | sqlGenerate.Sql.Insert(rightBracketIndex, " ) "); 106 | } 107 | 108 | return sqlGenerate; 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /core-data.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2027 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Overt.Core.Data", "src\Overt.Core.Data\Overt.Core.Data.csproj", "{8B1B556F-1D2C-49D2-8CB9-F9D2C7080786}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "core", "core", "{9DD521BB-DEE6-40A1-B042-EA89EB889546}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "net462", "net462", "{B159908C-321A-45AF-998B-C431D7D02070}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Overt.User.Domain", "src\net46\Overt.User.Domain\Overt.User.Domain.csproj", "{F34F6B13-B939-47A3-827E-E7015FD1B434}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Overt.Core.DataConsole", "src\core\Overt.Core.DataConsole\Overt.Core.DataConsole.csproj", "{D2349F1D-B2AB-40EE-980F-0F0AB8E3F970}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Overt.User.Application", "src\core\Overt.User.Application\Overt.User.Application.csproj", "{5D9B9D31-33CA-4378-AA58-D788C7EBD4CF}" 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Overt.User.Domain", "src\core\Overt.User.Domain\Overt.User.Domain.csproj", "{0558E8F8-BB9E-4C62-A8D0-03011ED77284}" 19 | EndProject 20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Overt.User.Application", "src\net46\Overt.User.Application\Overt.User.Application.csproj", "{5ADB2A33-42E4-484B-997E-3F8B942539E4}" 21 | EndProject 22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Overt.Core.DataConsole", "src\net46\Overt.Core.DataConsole\Overt.Core.DataConsole.csproj", "{F92F116B-A438-447B-9475-4D62AF197742}" 23 | EndProject 24 | Global 25 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 26 | Debug|Any CPU = Debug|Any CPU 27 | Release|Any CPU = Release|Any CPU 28 | EndGlobalSection 29 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 30 | {8B1B556F-1D2C-49D2-8CB9-F9D2C7080786}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {8B1B556F-1D2C-49D2-8CB9-F9D2C7080786}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {8B1B556F-1D2C-49D2-8CB9-F9D2C7080786}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {8B1B556F-1D2C-49D2-8CB9-F9D2C7080786}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {F34F6B13-B939-47A3-827E-E7015FD1B434}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {F34F6B13-B939-47A3-827E-E7015FD1B434}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {F34F6B13-B939-47A3-827E-E7015FD1B434}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {F34F6B13-B939-47A3-827E-E7015FD1B434}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {D2349F1D-B2AB-40EE-980F-0F0AB8E3F970}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {D2349F1D-B2AB-40EE-980F-0F0AB8E3F970}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {D2349F1D-B2AB-40EE-980F-0F0AB8E3F970}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {D2349F1D-B2AB-40EE-980F-0F0AB8E3F970}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {5D9B9D31-33CA-4378-AA58-D788C7EBD4CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {5D9B9D31-33CA-4378-AA58-D788C7EBD4CF}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {5D9B9D31-33CA-4378-AA58-D788C7EBD4CF}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {5D9B9D31-33CA-4378-AA58-D788C7EBD4CF}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {0558E8F8-BB9E-4C62-A8D0-03011ED77284}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {0558E8F8-BB9E-4C62-A8D0-03011ED77284}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {0558E8F8-BB9E-4C62-A8D0-03011ED77284}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {0558E8F8-BB9E-4C62-A8D0-03011ED77284}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {5ADB2A33-42E4-484B-997E-3F8B942539E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {5ADB2A33-42E4-484B-997E-3F8B942539E4}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {5ADB2A33-42E4-484B-997E-3F8B942539E4}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {5ADB2A33-42E4-484B-997E-3F8B942539E4}.Release|Any CPU.Build.0 = Release|Any CPU 54 | {F92F116B-A438-447B-9475-4D62AF197742}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 55 | {F92F116B-A438-447B-9475-4D62AF197742}.Debug|Any CPU.Build.0 = Debug|Any CPU 56 | {F92F116B-A438-447B-9475-4D62AF197742}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {F92F116B-A438-447B-9475-4D62AF197742}.Release|Any CPU.Build.0 = Release|Any CPU 58 | EndGlobalSection 59 | GlobalSection(SolutionProperties) = preSolution 60 | HideSolutionNode = FALSE 61 | EndGlobalSection 62 | GlobalSection(NestedProjects) = preSolution 63 | {F34F6B13-B939-47A3-827E-E7015FD1B434} = {B159908C-321A-45AF-998B-C431D7D02070} 64 | {D2349F1D-B2AB-40EE-980F-0F0AB8E3F970} = {9DD521BB-DEE6-40A1-B042-EA89EB889546} 65 | {5D9B9D31-33CA-4378-AA58-D788C7EBD4CF} = {9DD521BB-DEE6-40A1-B042-EA89EB889546} 66 | {0558E8F8-BB9E-4C62-A8D0-03011ED77284} = {9DD521BB-DEE6-40A1-B042-EA89EB889546} 67 | {5ADB2A33-42E4-484B-997E-3F8B942539E4} = {B159908C-321A-45AF-998B-C431D7D02070} 68 | {F92F116B-A438-447B-9475-4D62AF197742} = {B159908C-321A-45AF-998B-C431D7D02070} 69 | EndGlobalSection 70 | GlobalSection(ExtensibilityGlobals) = postSolution 71 | SolutionGuid = {63C9732F-DFAB-438C-B2F2-7C0399EF8701} 72 | EndGlobalSection 73 | EndGlobal 74 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/Overt.User.Application.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {5ADB2A33-42E4-484B-997E-3F8B942539E4} 8 | Library 9 | Properties 10 | Overt.User.Application 11 | Overt.User.Application 12 | v4.6.2 13 | 512 14 | true 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | ..\..\..\packages\Autofac.4.8.1\lib\net45\Autofac.dll 37 | 38 | 39 | ..\..\..\packages\AutoMapper.9.0.0\lib\net461\AutoMapper.dll 40 | 41 | 42 | ..\..\..\packages\MySql.Data.6.10.7\lib\net452\MySql.Data.dll 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | ..\..\..\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | {8b1b556f-1d2c-49d2-8cb9-f9d2c7080786} 85 | Overt.Core.Data 86 | 87 | 88 | {f34f6b13-b939-47a3-827e-e7015fd1b434} 89 | Overt.User.Domain 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/SqlExpression/SqlGenerate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Overt.Core.Data.Expressions 7 | { 8 | /// 9 | /// SqlGenrate 10 | /// 11 | public class SqlGenerate 12 | { 13 | #region Private Property 14 | private static readonly List S_listEnglishWords = new List { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", }; 15 | 16 | private Dictionary _dicTableName = new Dictionary(); 17 | private Queue _queueEnglishWords = new Queue(S_listEnglishWords); 18 | #endregion 19 | 20 | #region Public Property 21 | /// 22 | /// 字段 23 | /// 24 | public List SelectFields { get; set; } 25 | /// 26 | /// 表名 27 | /// 28 | public string TableName { get; set; } 29 | 30 | /// 31 | /// 字段字符串 32 | /// 33 | public string SelectFieldsStr 34 | { 35 | get 36 | { 37 | return string.Join(", ", this.SelectFields); 38 | } 39 | } 40 | 41 | /// 42 | /// sql长度 43 | /// 44 | public int Length 45 | { 46 | get 47 | { 48 | return Sql.Length; 49 | } 50 | } 51 | 52 | /// 53 | /// 脚本 54 | /// 55 | public StringBuilder Sql { get; set; } 56 | 57 | /// 58 | /// 数据库类型 59 | /// 60 | public DatabaseType DatabaseType { get; set; } 61 | 62 | /// 63 | /// 数据库参数 64 | /// 65 | public Dictionary DbParams { get; private set; } 66 | 67 | /// 68 | /// 索引数据 69 | /// 70 | /// 71 | /// 72 | public char this[int index] 73 | { 74 | get 75 | { 76 | return this.Sql[index]; 77 | } 78 | } 79 | #endregion 80 | 81 | 82 | #region Constructor 83 | /// 84 | /// 构造函数 85 | /// 86 | public SqlGenerate() 87 | { 88 | DbParams = new Dictionary(); 89 | Sql = new StringBuilder(); 90 | SelectFields = new List(); 91 | } 92 | 93 | /// 94 | /// 95 | /// 96 | /// 97 | /// 98 | /// 99 | public static SqlGenerate operator +(SqlGenerate sqlGenerate, string sql) 100 | { 101 | sqlGenerate.Sql.Append(sql); 102 | return sqlGenerate; 103 | } 104 | #endregion 105 | 106 | #region Public Method 107 | /// 108 | /// 清除 109 | /// 110 | public void Clear() 111 | { 112 | SelectFields.Clear(); 113 | Sql.Clear(); 114 | DbParams.Clear(); 115 | _dicTableName.Clear(); 116 | _queueEnglishWords = new Queue(S_listEnglishWords); 117 | } 118 | 119 | /// 120 | /// 替换最后一次出现字符 121 | /// 122 | /// 123 | /// 124 | public void RelaceLast(string oldStr, string newStr) 125 | { 126 | if (Sql.ToString().LastIndexOf(oldStr) == -1) 127 | return; 128 | 129 | Sql = Sql.Replace(oldStr, newStr, Sql.ToString().LastIndexOf(oldStr), newStr.Length); 130 | } 131 | 132 | /// 133 | /// 添加参数 134 | /// 135 | /// 136 | public void AddDbParameter(object parameterValue) 137 | { 138 | if (parameterValue == null || parameterValue == DBNull.Value) 139 | Sql.Append(" null"); 140 | else 141 | { 142 | var name = DatabaseType.ParamPrefix() + "param" + DbParams.Count; 143 | DbParams.Add(name, parameterValue); 144 | Sql.Append(" " + name); 145 | } 146 | } 147 | 148 | /// 149 | /// 拼接in参数 150 | /// 151 | /// 152 | public void CombineInParameters(List parameterValues) 153 | { 154 | if (parameterValues == null || parameterValues.Count == 0) 155 | return; 156 | Sql.Append(" " + $"({string.Join(",", parameterValues.Select(n => $"'{n}'"))})"); 157 | } 158 | 159 | /// 160 | /// ToString 161 | /// 162 | /// 163 | public override string ToString() 164 | { 165 | return Sql.ToString(); 166 | } 167 | #endregion 168 | } 169 | } -------------------------------------------------------------------------------- /src/Overt.Core.Data/DataContext/DataContext.cs: -------------------------------------------------------------------------------- 1 | #if ASP_NET_CORE 2 | using Microsoft.Extensions.Configuration; 3 | using System.IO; 4 | #endif 5 | using MySql.Data.MySqlClient; 6 | using System; 7 | #if !ASP_NET_CORE 8 | using System.Configuration; 9 | #endif 10 | using System.Data; 11 | using System.Data.Common; 12 | using System.Data.SqlClient; 13 | 14 | namespace Overt.Core.Data 15 | { 16 | /// 17 | /// 数据库连接工具类 18 | /// 19 | public class DataContext : IDisposable 20 | { 21 | #region Private Members 22 | readonly bool _isMaster; 23 | readonly string _dbStoreKey; 24 | DbProviderFactory _dbFactory; 25 | 26 | #if ASP_NET_CORE 27 | readonly IConfiguration _configuration; 28 | readonly Func _connectionFunc; 29 | #else 30 | readonly Func _connectionFunc; 31 | #endif 32 | 33 | 34 | #endregion 35 | 36 | #region Public Members 37 | /// 38 | /// 连接对象 39 | /// 40 | public IDbConnection DbConnection { get; private set; } 41 | #endregion 42 | 43 | #region Constructor 44 | #if ASP_NET_CORE 45 | /// 46 | /// 构造函数 47 | /// 48 | /// if null 则从appsettings.json中获取 49 | /// 是否从库 50 | /// 存储字符串标识 51 | /// 连接字符串Func 52 | public DataContext(IConfiguration configuration, bool isMaster = false, string dbStoreKey = "", Func connectionFunc = null) 53 | { 54 | _configuration = configuration; 55 | _isMaster = isMaster; 56 | _dbStoreKey = dbStoreKey; 57 | _connectionFunc = connectionFunc; 58 | 59 | // 打开连接 60 | CreateAndOpen(); 61 | } 62 | #else 63 | /// 64 | /// 构造函数 65 | /// 66 | /// 是否从库 67 | /// 存储字符串标识 68 | /// 连接字符串Func 69 | public DataContext(bool isMaster = false, string dbStoreKey = "", Func connectionFunc = null) 70 | { 71 | _isMaster = isMaster; 72 | _dbStoreKey = dbStoreKey; 73 | _connectionFunc = connectionFunc; 74 | 75 | // 打开连接 76 | CreateAndOpen(); 77 | } 78 | #endif 79 | #endregion 80 | 81 | #region Private Method 82 | /// 83 | /// 打开链接 84 | /// 85 | private void CreateAndOpen() 86 | { 87 | var connectionString = string.Empty; 88 | var settings = DataSettings.Default; 89 | 90 | // 获取连接 91 | #if ASP_NET_CORE 92 | var connectionSetting = settings.Get(_configuration, _isMaster, _dbStoreKey, _connectionFunc); 93 | connectionString = connectionSetting.Item1; 94 | _dbFactory = GetFactory(connectionSetting.Item2); 95 | #else 96 | var connectionSetting = settings.Get(_isMaster, _dbStoreKey, _connectionFunc); 97 | connectionString = connectionSetting?.ConnectionString; 98 | _dbFactory = DbProviderFactories.GetFactory(connectionSetting?.ProviderName); 99 | #endif 100 | 101 | if (string.IsNullOrEmpty(connectionString)) 102 | throw new Exception($"连接字符串获取为空,请检查Repository是否指定了dbStoreKey以及检查配置文件是否存在"); 103 | 104 | DbConnection = _dbFactory.CreateConnection(); 105 | DbConnection.ConnectionString = connectionString; 106 | if (DbConnection.State != ConnectionState.Open) 107 | DbConnection.Open(); 108 | } 109 | 110 | /// 111 | /// 获取Factory 112 | /// 113 | /// 114 | /// 115 | private DbProviderFactory GetFactory(DatabaseType dbType) 116 | { 117 | switch (dbType) 118 | { 119 | case DatabaseType.SqlServer: 120 | case DatabaseType.GteSqlServer2012: 121 | return SqlClientFactory.Instance; 122 | case DatabaseType.MySql: 123 | return MySqlClientFactory.Instance; 124 | case DatabaseType.PostgreSQL: 125 | return Npgsql.NpgsqlFactory.Instance; 126 | case DatabaseType.SQLite: 127 | #if ASP_NET_CORE 128 | AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data")); 129 | return Microsoft.Data.Sqlite.SqliteFactory.Instance; 130 | #else 131 | return System.Data.SQLite.SQLiteFactory.Instance; 132 | #endif 133 | } 134 | return null; 135 | } 136 | #endregion 137 | 138 | #region Public Method 139 | /// 140 | /// 垃圾回收 141 | /// 142 | public void Dispose() 143 | { 144 | if (DbConnection == null) 145 | return; 146 | try 147 | { 148 | DbConnection.Dispose(); 149 | } 150 | catch { } 151 | } 152 | #endregion 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/core/Overt.User.Application/Services/UserLongIdService.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Overt.User.Application.Constracts; 3 | using Overt.User.Application.Models; 4 | using Overt.User.Domain.Contracts; 5 | using Overt.User.Domain.Entities; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Threading.Tasks; 10 | 11 | namespace Overt.User.Application.Services 12 | { 13 | public class UserLongIdService : IUserLongIdService 14 | { 15 | IMapper _mapper; 16 | IUserLongIdRepository _userRepository; 17 | public UserLongIdService( 18 | IMapper mapper, 19 | IUserLongIdRepository userRepository) 20 | { 21 | _mapper = mapper; 22 | _userRepository = userRepository; 23 | } 24 | 25 | #region SyncMethod 26 | public long Add(UserPostModel model) 27 | { 28 | if (!model.IsValid(out Exception ex)) 29 | throw ex; 30 | 31 | var entity = _mapper.Map(model); 32 | entity.AddTime = DateTime.Now; 33 | var result = _userRepository.Add(entity, true); 34 | if (!result) 35 | throw new Exception($"新增失败"); 36 | 37 | var entity2 = _mapper.Map(model); 38 | entity2.AddTime = DateTime.Now; 39 | var result2 = _userRepository.Add(entity2); 40 | if (!result2) 41 | throw new Exception($"新增失败"); 42 | 43 | return entity.UserId; 44 | } 45 | 46 | public bool Add(params UserPostModel[] models) 47 | { 48 | if ((models?.Count() ?? 0) <= 0) 49 | throw new Exception("必须提供"); 50 | 51 | var entities = _mapper.Map>(models); 52 | entities.ForEach(oo => 53 | { 54 | oo.AddTime = DateTime.Now; 55 | }); 56 | var result = _userRepository.Add(entities.ToArray()); 57 | if (!result) 58 | throw new Exception($"新增失败"); 59 | return result; 60 | } 61 | 62 | public bool Delete(long userId) 63 | { 64 | if (userId <= 0) 65 | throw new Exception($"UserId必须大于0"); 66 | 67 | return _userRepository.Delete(oo => oo.UserId == userId); 68 | } 69 | 70 | public UserModel Get(long userId, bool isMaster = false) 71 | { 72 | if (userId <= 0) 73 | throw new Exception($"UserId必须大于0"); 74 | 75 | var entity = _userRepository.Get(oo => oo.UserId == userId, isMaster: isMaster); 76 | return _mapper.Map(entity); 77 | } 78 | 79 | public List GetList(List userIds, bool isMaster = false) 80 | { 81 | if ((userIds?.Count ?? 0) <= 0) 82 | throw new Exception($"UserIds至少提供一个"); 83 | 84 | var entities = _userRepository.GetList(1, userIds.Count, oo => userIds.Contains(oo.UserId), isMaster: isMaster); 85 | return _mapper.Map>(entities); 86 | } 87 | #endregion 88 | 89 | #region AsyncMethod 90 | public async Task AddAsync(UserPostModel model) 91 | { 92 | if (!model.IsValid(out Exception ex)) 93 | throw ex; 94 | 95 | var entity = _mapper.Map(model); 96 | entity.AddTime = DateTime.Now; 97 | var result = await _userRepository.AddAsync(entity, true); 98 | if (!result) 99 | throw new Exception($"新增失败"); 100 | return entity.UserId; 101 | } 102 | 103 | public async Task AddAsync(params UserPostModel[] models) 104 | { 105 | if ((models?.Count() ?? 0) <= 0) 106 | throw new Exception("必须提供"); 107 | 108 | var entities = _mapper.Map>(models); 109 | entities.ForEach(oo => 110 | { 111 | oo.AddTime = DateTime.Now; 112 | }); 113 | var result = await _userRepository.AddAsync(entities.ToArray()); 114 | if (!result) 115 | throw new Exception($"新增失败"); 116 | return result; 117 | } 118 | 119 | public async Task DeleteAsync(long userId) 120 | { 121 | if (userId <= 0) 122 | throw new Exception($"UserId必须大于0"); 123 | 124 | return await _userRepository.DeleteAsync(oo => oo.UserId == userId); 125 | } 126 | 127 | public async Task GetAsync(long userId, bool isMaster = false) 128 | { 129 | if (userId <= 0) 130 | throw new Exception($"UserId必须大于0"); 131 | 132 | var entity = await _userRepository.GetAsync(oo => oo.UserId == userId, isMaster: isMaster); 133 | return _mapper.Map(entity); 134 | } 135 | 136 | public async Task> GetListAsync(List userIds, bool isMaster = false) 137 | { 138 | if ((userIds?.Count ?? 0) <= 0) 139 | throw new Exception($"UserIds至少提供一个"); 140 | 141 | var entities = await _userRepository.GetListAsync(1, userIds.Count, oo => userIds.Contains(oo.UserId), isMaster: isMaster); 142 | return _mapper.Map>(entities); 143 | } 144 | #endregion 145 | 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/net46/Overt.User.Application/Services/UserService.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Overt.User.Application.Constracts; 3 | using Overt.User.Application.Models; 4 | using Overt.User.Domain.Contracts; 5 | using Overt.User.Domain.Entities; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Threading.Tasks; 9 | using System.Transactions; 10 | 11 | namespace Overt.User.Application.Services 12 | { 13 | public class UserService : IUserService 14 | { 15 | IMapper _mapper; 16 | IUserRepository _userRepository; 17 | ISubUserRepository _subUserRepository; 18 | public UserService( 19 | IMapper mapper, 20 | IUserRepository userRepository, 21 | ISubUserRepository subUserRepository) 22 | { 23 | _mapper = mapper; 24 | _userRepository = userRepository; 25 | _subUserRepository = subUserRepository; 26 | } 27 | 28 | public async Task AddAsync(UserPostModel model) 29 | { 30 | if (!model.IsValid(out Exception ex)) 31 | throw ex; 32 | 33 | var entity = _mapper.Map(model); 34 | entity.AddTime = DateTime.Now; 35 | var result = await _userRepository.AddAsync(entity, true); 36 | if (!result) 37 | throw new Exception($"新增失败"); 38 | return entity.UserId; 39 | } 40 | 41 | public async Task DeleteAsync(int userId) 42 | { 43 | if (userId <= 0) 44 | throw new Exception($"UserId必须大于0"); 45 | 46 | return await _userRepository.DeleteAsync(oo => oo.UserId == userId); 47 | } 48 | 49 | public async Task GetAsync(int userId, bool isMaster = false) 50 | { 51 | if (userId <= 0) 52 | throw new Exception($"UserId必须大于0"); 53 | 54 | var entity = await _userRepository.GetAsync(oo => oo.UserId == userId, isMaster: isMaster); 55 | return _mapper.Map(entity); 56 | } 57 | 58 | public async Task> GetListAsync(List userIds, bool isMaster = false) 59 | { 60 | if ((userIds?.Count ?? 0) <= 0) 61 | throw new Exception($"UserIds至少提供一个"); 62 | 63 | var entities = await _userRepository.GetListAsync(1, userIds.Count, oo => userIds.Contains(oo.UserId), isMaster: isMaster); 64 | return _mapper.Map>(entities); 65 | } 66 | 67 | public async Task<(int, List)> GetPageAsync(UserSearchModel model) 68 | { 69 | var expression = model.GetExpression(); 70 | var orders = model.GetOrder(); 71 | var count = await _userRepository.CountAsync(expression, model.IsMaster); 72 | var entities = await _userRepository.GetListAsync(model.Page, model.Size, expression, isMaster: model.IsMaster, orderByFields: orders); 73 | var models = _mapper.Map>(entities); 74 | return (count, models); 75 | } 76 | 77 | public async Task> OtherSqlAsync() 78 | { 79 | var result = await _userRepository.OtherSqlAsync(); 80 | return result; 81 | } 82 | 83 | public async Task UpdateAsync(int userId, bool isSex) 84 | { 85 | if (userId <= 0) 86 | throw new Exception($"UserId必须大于0"); 87 | 88 | // 第一种 89 | var dic = new Dictionary() 90 | { 91 | { nameof(UserEntity.IsSex), isSex } 92 | }; 93 | var updateResult1 = await _userRepository.SetAsync(() => dic, oo => oo.UserId == userId); 94 | 95 | // 第二种 96 | var updateResult2 = await _userRepository.SetAsync(() => new { IsSex = isSex }, oo => oo.UserId == userId); 97 | 98 | // 第三种 99 | var entity = await _userRepository.GetAsync(oo => oo.UserId == userId, isMaster: true); 100 | if (entity?.UserId != userId) 101 | throw new Exception($"无可更新数据"); 102 | entity.IsSex = isSex; 103 | var updateResult3 = await _userRepository.SetAsync(entity); 104 | 105 | return updateResult3; 106 | } 107 | 108 | public async Task ExecuteInTransactionAsync() 109 | { 110 | // 分布式事务 111 | using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) 112 | { 113 | var result = false; 114 | try 115 | { 116 | result = await _userRepository.AddAsync(new UserEntity() 117 | { 118 | UserName = "222222222", 119 | RealName = "22222222", 120 | Password = "123456", 121 | IsSex = false, 122 | JsonValue = "{}", 123 | AddTime = DateTime.Now 124 | }); 125 | result &= await _subUserRepository.AddAsync(new SubUserEntity() 126 | { 127 | UserName = "222222222", 128 | RealName = "22222222", 129 | Password = "123456", 130 | IsSex = false, 131 | JsonValue = "{}", 132 | AddTime = DateTime.Now 133 | }); 134 | 135 | scope.Complete(); 136 | return result; 137 | } 138 | catch(Exception ex) 139 | { 140 | // logger 141 | } 142 | return false; 143 | } 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/SqlExpression/SqlExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace Overt.Core.Data.Expressions 6 | { 7 | /// 8 | /// Expression => Sql 9 | /// 10 | public static class SqlExpression 11 | { 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | public static SqlExpressionCore Insert(DatabaseType dbType, string tableName = "", bool returnLastIdentity = false) 21 | { 22 | return new SqlExpressionCore(dbType, tableName).Insert(returnLastIdentity); 23 | } 24 | 25 | /// 26 | /// 删除 27 | /// 28 | /// 29 | /// 数据库类型 30 | /// 31 | /// 32 | public static SqlExpressionCore Delete(DatabaseType dbType, string tableName = "") 33 | { 34 | return new SqlExpressionCore(dbType, tableName).Delete(); 35 | } 36 | 37 | /// 38 | /// 修改 39 | /// 40 | /// 41 | /// 数据库类型 42 | /// 43 | /// 44 | /// 45 | public static SqlExpressionCore Update(DatabaseType dbType, Expression> expression = null, string tableName = "") 46 | { 47 | return new SqlExpressionCore(dbType, tableName).Update(expression); 48 | } 49 | 50 | /// 51 | /// 修改 52 | /// 53 | /// 54 | /// 数据库类型 55 | /// 56 | /// 57 | /// 58 | public static SqlExpressionCore Update(DatabaseType dbType, IEnumerable fields = null, string tableName = "") 59 | { 60 | return new SqlExpressionCore(dbType, tableName).Update(fields); 61 | } 62 | 63 | /// 64 | /// 查询 65 | /// 66 | /// 67 | /// 数据库类型 68 | /// 69 | /// 70 | /// 71 | public static SqlExpressionCore Select(DatabaseType dbType, Expression> expression = null, string tableName = "") 72 | { 73 | return new SqlExpressionCore(dbType, tableName).Select(expression); 74 | } 75 | 76 | /// 77 | /// 数量 78 | /// 79 | /// 80 | /// 数据库类型 81 | /// 82 | /// 83 | /// 84 | public static SqlExpressionCore Count(DatabaseType dbType, Expression> expression = null, string tableName = "") 85 | { 86 | return new SqlExpressionCore(dbType, tableName).Count(expression); 87 | } 88 | 89 | /// 90 | /// 最大 91 | /// 92 | /// 93 | /// 数据库类型 94 | /// 95 | /// 96 | /// 97 | public static SqlExpressionCore Max(DatabaseType dbType, Expression> expression, string tableName = "") 98 | { 99 | return new SqlExpressionCore(dbType, tableName).Max(expression); 100 | } 101 | 102 | /// 103 | /// 最小 104 | /// 105 | /// 106 | /// 数据库类型 107 | /// 108 | /// 109 | /// 110 | public static SqlExpressionCore Min(DatabaseType dbType, Expression> expression, string tableName = "") 111 | { 112 | return new SqlExpressionCore(dbType, tableName).Min(expression); 113 | } 114 | 115 | /// 116 | /// 平均值 117 | /// 118 | /// 119 | /// 数据库类型 120 | /// 121 | /// 122 | /// 123 | public static SqlExpressionCore Avg(DatabaseType dbType, Expression> expression, string tableName = "") 124 | { 125 | return new SqlExpressionCore(dbType, tableName).Avg(expression); 126 | } 127 | 128 | /// 129 | /// 求和 130 | /// 131 | /// 132 | /// 数据库类型 133 | /// 134 | /// 135 | /// 136 | public static SqlExpressionCore Sum(DatabaseType dbType, Expression> expression, string tableName = "") 137 | { 138 | return new SqlExpressionCore(dbType, tableName).Sum(expression); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/DataContext/DataSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | #if ASP_NET_CORE 4 | using Microsoft.Extensions.Configuration; 5 | #else 6 | using System.Configuration; 7 | #endif 8 | 9 | namespace Overt.Core.Data 10 | { 11 | /// 12 | /// 连接配置信息获取 13 | /// 1. master / secondary 14 | /// 2. xx.master / xx.secondary 15 | /// 16 | public class DataSettings 17 | { 18 | #region Static Private Members 19 | const string _connNmeOfMaster = "master"; 20 | const string _connNameOfSecondary = "secondary"; 21 | const string _connNameOfPoint = "."; 22 | #endregion 23 | 24 | #region Single Instance 25 | static readonly object lockHelper = new object(); 26 | static volatile DataSettings _Default; 27 | /// 28 | /// 单例模式 29 | /// 30 | static public DataSettings Default 31 | { 32 | get 33 | { 34 | if (_Default == null) 35 | { 36 | lock (lockHelper) 37 | { 38 | _Default = _Default ?? new DataSettings(); 39 | } 40 | } 41 | return _Default; 42 | } 43 | } 44 | #endregion 45 | 46 | #region Construct Method 47 | /// 48 | /// 构造函数 49 | /// 50 | private DataSettings() 51 | { 52 | } 53 | #endregion 54 | 55 | #region Public Method 56 | #if ASP_NET_CORE 57 | /// 58 | /// 获取连接字符串 59 | /// 60 | /// 61 | /// 62 | /// 63 | /// 64 | /// 65 | public (string, DatabaseType) Get(IConfiguration configuration, bool isMaster, string dbStoreKey, Func connectionFunc = null) 66 | { 67 | string connectionString; 68 | if (connectionFunc != null) 69 | { 70 | connectionString = connectionFunc.Invoke(isMaster); 71 | return ResolveConnectionString(connectionString); 72 | } 73 | 74 | if (configuration == null) 75 | { 76 | throw new Exception($"请注入IConfiguration"); 77 | //configuration = new ConfigurationBuilder() 78 | // .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) 79 | // .AddJsonFile("appsettings.json") 80 | // .Build(); 81 | } 82 | 83 | var connectionKey = GetKey(isMaster, dbStoreKey); 84 | connectionString = configuration.GetConnectionString(connectionKey); 85 | if (string.IsNullOrEmpty(connectionString) && !isMaster) 86 | { 87 | // 从库转主库 88 | connectionKey = GetKey(true, dbStoreKey); 89 | connectionString = configuration.GetConnectionString(connectionKey); 90 | } 91 | 92 | return ResolveConnectionString(connectionString); 93 | } 94 | 95 | /// 96 | /// 解析 97 | /// 98 | /// 99 | /// 100 | /// 101 | private (string, DatabaseType) ResolveConnectionString(string connectionString, string param = "DbType") 102 | { 103 | var dbTypeRegex = new Regex($@"(^|;){param}=(?[A-Za-z]+)(;|$)"); 104 | var m = dbTypeRegex.Match(connectionString); 105 | var dbTypeString = m?.Groups["dbtype"].Value; 106 | DatabaseType dbType; 107 | var parseResult = Enum.TryParse(dbTypeString, out dbType); 108 | if (!parseResult) 109 | dbType = DatabaseType.MySql; 110 | 111 | connectionString = Regex.Replace(connectionString, $@"{param}=([A-Za-z]+)(;|$)", ""); 112 | return (connectionString, dbType); 113 | } 114 | #else 115 | /// 116 | /// 获取连接字符串 117 | /// 118 | /// 119 | /// 120 | /// 121 | /// 122 | public ConnectionStringSettings Get(bool isMaster, string dbStoreKey, Func connectionFunc = null) 123 | { 124 | if (connectionFunc != null) 125 | return connectionFunc.Invoke(isMaster); 126 | 127 | var connectionKey = GetKey(isMaster, dbStoreKey); 128 | var connectionSetting = ConfigurationManager.ConnectionStrings[connectionKey]; 129 | if (string.IsNullOrEmpty(connectionSetting?.ConnectionString) && !isMaster) 130 | { 131 | connectionKey = GetKey(true, dbStoreKey); 132 | connectionSetting = ConfigurationManager.ConnectionStrings[connectionKey]; 133 | } 134 | return connectionSetting; 135 | } 136 | #endif 137 | #endregion 138 | 139 | #region Private Method 140 | /// 141 | /// 获取 142 | /// 143 | /// 144 | /// 不能包含点 145 | /// 146 | private string GetKey(bool isMaster = false, string dbStoreKey = "") 147 | { 148 | var connNameOfPrefix = string.IsNullOrWhiteSpace(dbStoreKey) ? "" : $"{dbStoreKey}{_connNameOfPoint}"; 149 | string connName; 150 | if (isMaster) 151 | connName = $"{connNameOfPrefix}{_connNmeOfMaster}"; 152 | else 153 | connName = $"{connNameOfPrefix}{_connNameOfSecondary}"; 154 | 155 | return connName; 156 | } 157 | #endregion 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/SqlExpression/Resolve/MethodCallSqlExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace Overt.Core.Data.Expressions 6 | { 7 | class MethodCallSqlExpression : BaseSqlExpression 8 | { 9 | static Dictionary> _Methods = new Dictionary> 10 | { 11 | {"In", In}, 12 | {"Equals", Equals}, 13 | {"Contains", Contains}, 14 | {"StartsWith", StartsWith}, 15 | {"EndsWith", EndsWith}, 16 | {"Format", Format} 17 | }; 18 | 19 | private static new void In(MethodCallExpression expression, SqlGenerate sqlGenerate) 20 | { 21 | SqlExpressionProvider.Where(expression.Arguments[0], sqlGenerate); 22 | sqlGenerate += " in "; 23 | SqlExpressionProvider.In(expression.Arguments[1], sqlGenerate); 24 | } 25 | 26 | private static void Equals(MethodCallExpression expression, SqlGenerate sqlGenerate) 27 | { 28 | SqlExpressionProvider.Where(expression.Object, sqlGenerate); 29 | sqlGenerate += " = "; 30 | SqlExpressionProvider.Where(expression.Arguments[0], sqlGenerate); 31 | } 32 | 33 | private static void Contains(MethodCallExpression expression, SqlGenerate sqlGenerate) 34 | { 35 | if (IsStaticArrayMethod(expression)) 36 | { 37 | DoStaticArrayMethodCall(expression, sqlGenerate); 38 | return; 39 | } 40 | if (IsEnumerableMethod(expression)) 41 | { 42 | DoEnumerableMethodCall(expression, sqlGenerate); 43 | return; 44 | } 45 | 46 | SqlExpressionProvider.Where(expression.Object, sqlGenerate); 47 | sqlGenerate += " like "; 48 | var val = SqlExpressionCompiler.Evaluate(expression.Arguments[0]); 49 | sqlGenerate.AddDbParameter($"%{val}%"); 50 | } 51 | 52 | private static void EndsWith(MethodCallExpression expression, SqlGenerate sqlGenerate) 53 | { 54 | SqlExpressionProvider.Where(expression.Object, sqlGenerate); 55 | //SqlExpressionProvider.Where(expression.Arguments[0], sqlGenerate); 56 | sqlGenerate += " like "; 57 | 58 | var val = SqlExpressionCompiler.Evaluate(expression.Arguments[0]); 59 | sqlGenerate.AddDbParameter($"%{val}"); 60 | } 61 | 62 | private static void StartsWith(MethodCallExpression expression, SqlGenerate sqlGenerate) 63 | { 64 | SqlExpressionProvider.Where(expression.Object, sqlGenerate); 65 | //SqlExpressionProvider.Where(expression.Arguments[0], sqlGenerate); 66 | sqlGenerate += " like "; 67 | 68 | var val = SqlExpressionCompiler.Evaluate(expression.Arguments[0]); 69 | sqlGenerate.AddDbParameter($"{val}%"); 70 | } 71 | 72 | private static void Format(MethodCallExpression expression, SqlGenerate sqlGenerate) 73 | { 74 | var formatString = SqlExpressionCompiler.Evaluate(expression.Arguments[0]); 75 | var formatArgs = new List(); 76 | var args = expression.Arguments; 77 | if (args.Count > 1) 78 | { 79 | for (int i = 1; i < args.Count; i++) 80 | { 81 | var val = SqlExpressionCompiler.Evaluate(expression.Arguments[i]); 82 | formatArgs.Add(val?.ToString()); 83 | } 84 | } 85 | sqlGenerate += string.Format(formatString.ToString(), formatArgs.ToArray()); 86 | } 87 | 88 | protected override SqlGenerate Where(MethodCallExpression expression, SqlGenerate sqlGenerate) 89 | { 90 | var key = expression.Method; 91 | if (key.IsGenericMethod) 92 | key = key.GetGenericMethodDefinition(); 93 | 94 | Action action; 95 | if (_Methods.TryGetValue(key.Name, out action)) 96 | { 97 | action(expression, sqlGenerate); 98 | return sqlGenerate; 99 | } 100 | 101 | throw new NotImplementedException("无法解析方法" + expression.Method); 102 | } 103 | 104 | protected override SqlGenerate Update(MethodCallExpression expression, SqlGenerate sqlGenerate) 105 | { 106 | var key = expression.Method; 107 | if (key.IsGenericMethod) 108 | key = key.GetGenericMethodDefinition(); 109 | 110 | Action action; 111 | if (_Methods.TryGetValue(key.Name, out action)) 112 | { 113 | action(expression, sqlGenerate); 114 | return sqlGenerate; 115 | } 116 | 117 | throw new NotImplementedException("无法解析方法" + expression.Method); 118 | } 119 | 120 | 121 | #region Internal Method 122 | 123 | internal static void DoEnumerableMethodCall(MethodCallExpression expression, SqlGenerate sqlGenerate) 124 | { 125 | SqlExpressionProvider.Where(expression.Arguments[0], sqlGenerate); 126 | sqlGenerate += " in "; 127 | SqlExpressionProvider.In(expression.Object, sqlGenerate); 128 | } 129 | 130 | internal static void DoStaticArrayMethodCall(MethodCallExpression expression, SqlGenerate sqlGenerate) 131 | { 132 | SqlExpressionProvider.Where(expression.Arguments[expression.Arguments.Count - 1], sqlGenerate); 133 | sqlGenerate += " in "; 134 | 135 | var memberExpr = expression.Arguments[0]; 136 | if (memberExpr.NodeType == ExpressionType.MemberAccess) 137 | memberExpr = expression.Arguments[0] as MemberExpression; 138 | 139 | SqlExpressionProvider.In(memberExpr, sqlGenerate); 140 | } 141 | 142 | #endregion 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/SqlExpression/SqlExpressionProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace Overt.Core.Data.Expressions 5 | { 6 | internal class SqlExpressionProvider 7 | { 8 | internal static ISqlExpression GetSqlExpression(Expression expression) 9 | { 10 | if (expression == null) 11 | { 12 | throw new ArgumentNullException("expression", "不能为null"); 13 | } 14 | 15 | if (expression is LambdaExpression) 16 | { 17 | return new LambdaSqlExpression(); 18 | } 19 | 20 | if (expression is BinaryExpression) 21 | { 22 | return new BinarySqlExpression(); 23 | } 24 | if (expression is BlockExpression) 25 | { 26 | throw new NotImplementedException("未实现的BlockSqlExpression"); 27 | } 28 | if (expression is ConditionalExpression) 29 | { 30 | throw new NotImplementedException("未实现的ConditionalSqlExpression"); 31 | } 32 | if (expression is ConstantExpression) 33 | { 34 | return new ConstantSqlExpression(); 35 | } 36 | if (expression is DebugInfoExpression) 37 | { 38 | throw new NotImplementedException("未实现的DebugInfoSqlExpression"); 39 | } 40 | if (expression is DefaultExpression) 41 | { 42 | throw new NotImplementedException("未实现的DefaultSqlExpression"); 43 | } 44 | if (expression is DynamicExpression) 45 | { 46 | throw new NotImplementedException("未实现的DynamicSqlExpression"); 47 | } 48 | if (expression is GotoExpression) 49 | { 50 | throw new NotImplementedException("未实现的GotoSqlExpression"); 51 | } 52 | if (expression is IndexExpression) 53 | { 54 | throw new NotImplementedException("未实现的IndexSqlExpression"); 55 | } 56 | if (expression is InvocationExpression) 57 | { 58 | throw new NotImplementedException("未实现的InvocationSqlExpression"); 59 | } 60 | if (expression is LabelExpression) 61 | { 62 | throw new NotImplementedException("未实现的LabelSqlExpression"); 63 | } 64 | if (expression is LambdaExpression) 65 | { 66 | throw new NotImplementedException("未实现的LambdaSqlExpression"); 67 | } 68 | if (expression is ListInitExpression) 69 | { 70 | return new ListInitSqlExpression(); 71 | } 72 | if (expression is LoopExpression) 73 | { 74 | throw new NotImplementedException("未实现的LoopSqlExpression"); 75 | } 76 | if (expression is MemberExpression) 77 | { 78 | return new MemberSqlExpression(); 79 | } 80 | if (expression is MemberInitExpression) 81 | { 82 | throw new NotImplementedException("未实现的MemberInitSqlExpression"); 83 | } 84 | if (expression is MethodCallExpression) 85 | { 86 | return new MethodCallSqlExpression(); 87 | } 88 | if (expression is NewArrayExpression) 89 | { 90 | return new NewArraySqlExpression(); 91 | } 92 | if (expression is NewExpression) 93 | { 94 | return new NewSqlExpression(); 95 | } 96 | if (expression is ParameterExpression) 97 | { 98 | throw new NotImplementedException("未实现的ParameterSqlExpression"); 99 | } 100 | if (expression is RuntimeVariablesExpression) 101 | { 102 | throw new NotImplementedException("未实现的RuntimeVariablesSqlExpression"); 103 | } 104 | if (expression is SwitchExpression) 105 | { 106 | throw new NotImplementedException("未实现的SwitchSqlExpression"); 107 | } 108 | if (expression is TryExpression) 109 | { 110 | throw new NotImplementedException("未实现的TrySqlExpression"); 111 | } 112 | if (expression is TypeBinaryExpression) 113 | { 114 | throw new NotImplementedException("未实现的TypeBinarySqlExpression"); 115 | } 116 | if (expression is UnaryExpression) 117 | { 118 | return new UnarySqlExpression(); 119 | } 120 | throw new NotImplementedException("未实现的SqlExpression"); 121 | } 122 | 123 | public static void Update(Expression expression, SqlGenerate sqlGenerate) 124 | { 125 | GetSqlExpression(expression).Update(expression, sqlGenerate); 126 | } 127 | 128 | public static void Select(Expression expression, SqlGenerate sqlGenerate) 129 | { 130 | GetSqlExpression(expression).Select(expression, sqlGenerate); 131 | } 132 | 133 | public static void Where(Expression expression, SqlGenerate sqlGenerate) 134 | { 135 | GetSqlExpression(expression).Where(expression, sqlGenerate); 136 | } 137 | 138 | public static void In(Expression expression, SqlGenerate sqlGenerate) 139 | { 140 | GetSqlExpression(expression).In(expression, sqlGenerate); 141 | } 142 | 143 | public static void OrderBy(Expression expression, SqlGenerate sqlGenerate) 144 | { 145 | GetSqlExpression(expression).OrderBy(expression, sqlGenerate); 146 | } 147 | 148 | public static void Max(Expression expression, SqlGenerate sqlGenerate) 149 | { 150 | GetSqlExpression(expression).Max(expression, sqlGenerate); 151 | } 152 | 153 | public static void Min(Expression expression, SqlGenerate sqlGenerate) 154 | { 155 | GetSqlExpression(expression).Min(expression, sqlGenerate); 156 | } 157 | 158 | public static void Avg(Expression expression, SqlGenerate sqlGenerate) 159 | { 160 | GetSqlExpression(expression).Avg(expression, sqlGenerate); 161 | } 162 | 163 | public static void Count(Expression expression, SqlGenerate sqlGenerate) 164 | { 165 | GetSqlExpression(expression).Count(expression, sqlGenerate); 166 | } 167 | 168 | public static void Sum(Expression expression, SqlGenerate sqlGenerate) 169 | { 170 | GetSqlExpression(expression).Sum(expression, sqlGenerate); 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Expressions/SqlExpression/Resolve/MemberSqlExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | 7 | namespace Overt.Core.Data.Expressions 8 | { 9 | class MemberSqlExpression : BaseSqlExpression 10 | { 11 | protected override SqlGenerate Select(MemberExpression expression, SqlGenerate sqlGenerate) 12 | { 13 | if (IsEnumerable(expression)) 14 | { 15 | var result = SqlExpressionCompiler.Evaluate(expression); 16 | var fields = (result as IEnumerable).Flatten(); 17 | if (fields?.Count > 0) 18 | sqlGenerate.SelectFields.AddRange(fields.Select(field => field.ToString().ParamSql(sqlGenerate))); 19 | else 20 | sqlGenerate.SelectFields = new List() { "*" }; 21 | 22 | return sqlGenerate; 23 | } 24 | 25 | sqlGenerate.SelectFields.Add(expression.Member.Name.ParamSql(sqlGenerate)); 26 | return sqlGenerate; 27 | } 28 | 29 | protected override SqlGenerate Where(MemberExpression expression, SqlGenerate sqlGenerate) 30 | { 31 | if (expression.Expression != null) 32 | { 33 | if (expression.Member.DeclaringType.IsNullableType()) 34 | { 35 | if (expression.Member.Name == "Value") //Can't use C# 6 yet: nameof(Nullable.Value) 36 | { 37 | SqlExpressionProvider.Where(expression.Expression, sqlGenerate); 38 | return sqlGenerate; 39 | } 40 | if (expression.Member.Name == "HasValue") 41 | { 42 | var doesNotEqualNull = Expression.MakeBinary(ExpressionType.NotEqual, expression.Expression, Expression.Constant(null)); 43 | SqlExpressionProvider.Where(doesNotEqualNull, sqlGenerate); 44 | return sqlGenerate; 45 | } 46 | throw new ArgumentException($"Expression '{expression}' accesses unsupported property '{expression.Member}' of Nullable"); 47 | } 48 | 49 | if (expression.IsParameterOrConvertAccess()) 50 | { 51 | sqlGenerate += $" {expression.Member.Name.ParamSql(sqlGenerate)}"; 52 | return sqlGenerate; 53 | } 54 | } 55 | 56 | var val = SqlExpressionCompiler.Evaluate(expression); 57 | sqlGenerate.AddDbParameter(val); 58 | return sqlGenerate; 59 | 60 | } 61 | 62 | protected override SqlGenerate In(MemberExpression expression, SqlGenerate sqlGenerate) 63 | { 64 | var result = SqlExpressionCompiler.Evaluate(expression); 65 | var inArgs = (result as IEnumerable).Flatten(); 66 | if (sqlGenerate.DatabaseType == DatabaseType.PostgreSQL) // pg的in查询需要手动拼接,不然npgsql客户不支持list类型参数化 67 | sqlGenerate.CombineInParameters(inArgs); 68 | else 69 | sqlGenerate.AddDbParameter(inArgs); 70 | return sqlGenerate; 71 | } 72 | 73 | protected override SqlGenerate OrderBy(MemberExpression expression, SqlGenerate sqlGenerate) 74 | { 75 | sqlGenerate += expression.Member.Name.ParamSql(sqlGenerate); 76 | return sqlGenerate; 77 | } 78 | 79 | protected override SqlGenerate Update(MemberExpression expression, SqlGenerate sqlGenerate) 80 | { 81 | var obj = SqlExpressionCompiler.Evaluate(expression); 82 | if (obj == null) 83 | throw new ArgumentException($"Expression '{expression}' accesses unsupported property '{expression.Member}' of Nullable"); 84 | 85 | if (obj.GetType().IsValueType) 86 | throw new ArgumentException($"Expression '{expression}' accesses unsupported valuetype"); 87 | 88 | if (obj.GetType() == typeof(string)) 89 | { 90 | sqlGenerate += obj.ToString(); 91 | } 92 | else if (obj is IDictionary dictionary) 93 | { 94 | foreach (string key in dictionary.Keys) 95 | { 96 | sqlGenerate += $"{key.ParamSql(sqlGenerate)} = "; 97 | sqlGenerate.AddDbParameter(dictionary[key]); 98 | sqlGenerate += ","; 99 | } 100 | } 101 | else 102 | { 103 | var pis = obj.GetType().GetProperties(); 104 | foreach (var p in pis) 105 | { 106 | sqlGenerate += $"{p.Name.ParamSql(sqlGenerate)} = "; 107 | sqlGenerate.AddDbParameter(p.GetValue(obj)); 108 | sqlGenerate += ","; 109 | } 110 | } 111 | 112 | if (sqlGenerate[sqlGenerate.Length - 1] == ',') 113 | sqlGenerate.Sql.Remove(sqlGenerate.Length - 1, 1); 114 | 115 | return sqlGenerate; 116 | } 117 | 118 | protected override SqlGenerate Max(MemberExpression expression, SqlGenerate sqlGenerate) 119 | { 120 | sqlGenerate.Sql.AppendFormat("select max({0}) from {1}", expression.Member.Name.ParamSql(sqlGenerate), sqlGenerate.TableName); 121 | return sqlGenerate; 122 | } 123 | 124 | protected override SqlGenerate Min(MemberExpression expression, SqlGenerate sqlGenerate) 125 | { 126 | sqlGenerate.Sql.AppendFormat("select min({0}) from {1}", expression.Member.Name.ParamSql(sqlGenerate), sqlGenerate.TableName); 127 | return sqlGenerate; 128 | } 129 | 130 | protected override SqlGenerate Avg(MemberExpression expression, SqlGenerate sqlGenerate) 131 | { 132 | sqlGenerate.Sql.AppendFormat("select avg({0}) from {1}", expression.Member.Name.ParamSql(sqlGenerate), sqlGenerate.TableName); 133 | return sqlGenerate; 134 | } 135 | 136 | protected override SqlGenerate Count(MemberExpression expression, SqlGenerate sqlGenerate) 137 | { 138 | sqlGenerate.Sql.AppendFormat("select count({0}) from {1}", expression.Member.Name.ParamSql(sqlGenerate), sqlGenerate.TableName); 139 | return sqlGenerate; 140 | } 141 | 142 | protected override SqlGenerate Sum(MemberExpression expression, SqlGenerate sqlGenerate) 143 | { 144 | sqlGenerate.Sql.AppendFormat("select sum({0}) from {1}", expression.Member.Name.ParamSql(sqlGenerate), sqlGenerate.TableName); 145 | return sqlGenerate; 146 | } 147 | 148 | /// 149 | /// 是否是集合方法 150 | /// 151 | /// 152 | /// 153 | internal static bool IsEnumerable(MemberExpression m) 154 | { 155 | return m.Type.IsOrHasGenericInterfaceTypeOf(typeof(IEnumerable<>)) 156 | && m.Type != typeof(string); 157 | } 158 | } 159 | } -------------------------------------------------------------------------------- /src/net46/Overt.Core.DataConsole/Overt.Core.DataConsole.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Debug 7 | AnyCPU 8 | {F92F116B-A438-447B-9475-4D62AF197742} 9 | Exe 10 | Overt.Core.DataConsole 11 | Overt.Core.DataConsole 12 | v4.6.2 13 | 512 14 | true 15 | true 16 | 17 | 18 | 19 | 20 | 21 | AnyCPU 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | 30 | 31 | AnyCPU 32 | pdbonly 33 | true 34 | bin\Release\ 35 | TRACE 36 | prompt 37 | 4 38 | 39 | 40 | 41 | ..\..\..\packages\Autofac.4.8.1\lib\net45\Autofac.dll 42 | 43 | 44 | ..\..\..\packages\AutoMapper.9.0.0\lib\net461\AutoMapper.dll 45 | 46 | 47 | ..\..\..\packages\EntityFramework.6.3.0\lib\net45\EntityFramework.dll 48 | 49 | 50 | ..\..\..\packages\EntityFramework.6.3.0\lib\net45\EntityFramework.SqlServer.dll 51 | 52 | 53 | 54 | 55 | 56 | ..\..\..\packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.113.3\lib\net46\System.Data.SQLite.dll 57 | True 58 | 59 | 60 | ..\..\..\packages\System.Data.SQLite.EF6.1.0.113.0\lib\net46\System.Data.SQLite.EF6.dll 61 | True 62 | 63 | 64 | ..\..\..\packages\System.Data.SQLite.Linq.1.0.113.0\lib\net46\System.Data.SQLite.Linq.dll 65 | True 66 | 67 | 68 | ..\..\..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | {8b1b556f-1d2c-49d2-8cb9-f9d2c7080786} 90 | Overt.Core.Data 91 | 92 | 93 | {5adb2a33-42e4-484b-997e-3f8b942539e4} 94 | Overt.User.Application 95 | 96 | 97 | {F34F6B13-B939-47A3-827E-E7015FD1B434} 98 | Overt.User.Domain 99 | 100 | 101 | 102 | 103 | 104 | 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /src/Overt.Core.Data/Extensions/SqlAlias.Extensions.cs: -------------------------------------------------------------------------------- 1 | using Overt.Core.Data.Expressions; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Reflection; 6 | 7 | namespace Overt.Core.Data 8 | { 9 | /// 10 | /// Sql别名 11 | /// 12 | public static class SqlAliasExtensions 13 | { 14 | /// 15 | /// 参数前缀 16 | /// 17 | /// 18 | /// 19 | public static string ParamPrefix(this DatabaseType dbType) 20 | { 21 | switch (dbType) 22 | { 23 | case DatabaseType.SqlServer: 24 | case DatabaseType.GteSqlServer2012: 25 | return "@"; 26 | case DatabaseType.MySql: 27 | return "?"; 28 | case DatabaseType.SQLite: 29 | return "@"; 30 | case DatabaseType.PostgreSQL: 31 | return "@"; 32 | default: 33 | return string.Empty; 34 | } 35 | } 36 | 37 | /// 38 | /// 获取添加左右标记 防止有关键字作为字段名/表名 39 | /// 40 | /// 41 | /// 42 | /// 43 | public static string ParamSql(this string columnName, SqlGenerate sqlGenerate) 44 | { 45 | return columnName.ParamSql(sqlGenerate?.DatabaseType); 46 | } 47 | 48 | /// 49 | /// 获取添加左右标记 防止有关键字作为字段名/表名 50 | /// 51 | /// 52 | /// 53 | /// 54 | public static string ParamSql(this string columnName, DatabaseType? dbType) 55 | { 56 | switch (dbType) 57 | { 58 | case DatabaseType.SqlServer: 59 | case DatabaseType.GteSqlServer2012: 60 | if (columnName.StartsWith("[")) 61 | return columnName; 62 | return $"[{columnName}]"; 63 | case DatabaseType.MySql: 64 | if (columnName.StartsWith("`")) 65 | return columnName; 66 | return $"`{columnName}`"; 67 | case DatabaseType.SQLite: 68 | if (columnName.StartsWith("`")) 69 | return columnName; 70 | return $"`{columnName}`"; 71 | case DatabaseType.PostgreSQL: 72 | if (columnName.StartsWith("\"")) 73 | return columnName; 74 | return $"\"{columnName}\""; 75 | default: 76 | return columnName; 77 | } 78 | } 79 | 80 | /// 81 | /// 获取添加字段 82 | /// 83 | /// 84 | /// 85 | /// 86 | /// 87 | public static string ParamValue(this string columnName, DatabaseType? dbType, List customFields) 88 | { 89 | switch (dbType) 90 | { 91 | case DatabaseType.SqlServer: 92 | case DatabaseType.GteSqlServer2012: 93 | return $"@{columnName}"; 94 | case DatabaseType.MySql: 95 | return $"@{columnName}"; 96 | case DatabaseType.SQLite: 97 | return $"@{columnName}"; 98 | case DatabaseType.PostgreSQL: 99 | var customPi = customFields?.FirstOrDefault(p=>p.Name.Equals(columnName)); 100 | if (customPi != null) 101 | { 102 | var attribute = customPi.GetAttribute(); 103 | if (attribute != null && attribute.CustomDataType.ToLower() == DataCustomType.Jsonb.ToString().ToLower()) 104 | return $"CAST(@{columnName} AS json)"; 105 | return $"@{columnName}"; 106 | } 107 | return $"@{columnName}"; 108 | default: 109 | return $"@{columnName}"; 110 | } 111 | } 112 | 113 | /// 114 | /// 获取最后一次Insert 115 | /// 116 | /// 117 | /// 118 | public static string SelectLastIdentity(this DatabaseType dbType) 119 | { 120 | switch (dbType) 121 | { 122 | case DatabaseType.SqlServer: 123 | case DatabaseType.GteSqlServer2012: 124 | return " select @@Identity"; 125 | case DatabaseType.MySql: 126 | return " select LAST_INSERT_ID();"; 127 | case DatabaseType.SQLite: 128 | return " select last_insert_rowid();"; 129 | case DatabaseType.PostgreSQL: 130 | return " select LASTVAL();"; 131 | default: 132 | return string.Empty; 133 | } 134 | } 135 | 136 | /// 137 | /// 是否存在表 138 | /// 139 | /// 140 | /// 141 | /// 142 | /// 143 | public static string ExistTableSql(this DatabaseType dbType, string dbName, string tableName) 144 | { 145 | switch (dbType) 146 | { 147 | case DatabaseType.SqlServer: 148 | case DatabaseType.GteSqlServer2012: 149 | return $"select count(1) from sys.tables where name='{tableName}' and type = 'u'"; 150 | case DatabaseType.MySql: 151 | return $"select count(1) from information_schema.tables where table_schema = '{dbName}' and table_name = '{tableName}'"; 152 | case DatabaseType.SQLite: 153 | return $"select count(1) from sqlite_master where type = 'table' and name='{tableName}'"; 154 | case DatabaseType.PostgreSQL: 155 | return $"select count(1) from pg_class where relname = '{tableName}';"; 156 | default: return string.Empty; 157 | } 158 | } 159 | 160 | /// 161 | /// 是否存在字段 162 | /// 163 | /// 164 | /// 165 | /// 166 | /// 167 | /// 168 | public static string ExistFieldSql(this DatabaseType dbType, string dbName, string tableName, string fieldName) 169 | { 170 | switch (dbType) 171 | { 172 | case DatabaseType.SqlServer: 173 | case DatabaseType.GteSqlServer2012: 174 | return $"select count(1) sys.columns where object_id = object_id('{tableName}') and name='{fieldName}'"; 175 | case DatabaseType.MySql: 176 | return $"select count(1) from information_schema.columns where table_schema = '{dbName}' and table_name = '{tableName}' and column_name = '{fieldName}'"; 177 | case DatabaseType.SQLite: 178 | return $"select * from sqlite_master where name='{tableName}' and sql like '%{fieldName}%';"; 179 | case DatabaseType.PostgreSQL: 180 | return $"select count(1) from information_schema.columns WHERE table_schema = '{dbName}' and table_name = '{tableName}' and column_name = '{fieldName}'"; 181 | default: return string.Empty; 182 | } 183 | } 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 如有疑问可直接加QQ:2292709323,微信:yaofengv,联系 2 | 3 | # Overt.Core.Data 4 | 5 | ### 项目层次说明 6 | 7 | > Overt.Core.Data v2.2.3 8 | > 基于dapper封装的expression om,让CURD更简单 9 | 10 | #### 1. 项目目录 11 | 12 | ``` 13 | |-Attrubute 特性 14 | | |-SubmeterAttrubute.cs 分表标识特性 (已废弃) 15 | | 16 | |-Contract 契约层 17 | | |-IPropertyAssist.cs 统一的接口定义文件,所有的数据层接口均继承 18 | | |-IBaseRepository.cs 基础接口类,包含增删改查,以及继承IDbRepository 19 | | 20 | |-DataContext 数据库连接层 21 | | |-DataContext.cs 数据库连接工厂类 22 | | |-DataContextConfig.cs 数据库配置信息获取类 23 | | 24 | |-Enums 枚举 25 | | |-DatabaseType.cs 数据库类型 26 | | |-FieldSortType.cs Asc / Desc 27 | | 28 | |-Expressions 表达式解析器(略) 29 | | 30 | |-Extensions Dapper扩展 31 | | |-Dapper.Extension.cs 扩展类 32 | | 33 | |-Params 参数实体 34 | | |-OrderByField.cs 排序类 35 | | 36 | |-Repositry 契约实现层 37 | | |-PropertyAssist.cs 抽象类,继承IPropertyAssist,virtual 38 | | |-BaseRepository.cs 抽象类,实现 IBaseRepository,virtual 39 | ``` 40 | 41 | 42 | #### 2. 版本及支持 43 | 44 | > * Nuget版本:V2.2.3 45 | > * 框架支持: Framework4.6.1 - NetStandard 2.0 46 | > * 数据库支持:MySql / SqlServer / SQLite [使用详见下文] 47 | 48 | 49 | #### 3. 项目依赖 50 | 51 | > * Framework 4.6.1 52 | 53 | ``` 54 | Dapper 2.0.35 55 | MySql.Data 8.0.20 56 | System.Data.SqlClient 4.8.1 57 | System.Data.SQLite 1.0.113.1 58 | System.ComponentModel.DataAnnotations 4.7.0 59 | ``` 60 | 61 | > * NetStandard 2.0 62 | 63 | ``` 64 | Dapper 2.0.35 65 | Microsoft.Data.Sqlite 3.1.5 66 | MySql.Data 8.0.20 67 | System.Data.SqlClient 4.8.1 68 | System.ComponentModel.DataAnnotations 4.7.0 69 | Microsoft.Extensions.Configuration 2.0.0 70 | 71 | ``` 72 | 73 | 74 | ### 使用 75 | 76 | #### 1. 配置信息 77 | 78 | > * 支持 IConfiguration 对象注入 79 | > * 支持默认配置文件appsettings.json 80 | > * 支持环境变量,或者使用外部的第三方配置中心(appolo),最终还是依赖于微软自身Configuration 81 | > * Core(DbType=MySql|SqlServer|SQLite): 82 | 83 | ``` 84 | [mysql]: DataSource=127.0.0.1;Database=TestDb;uid=root;pwd=123456;Allow Zero Datetime=True;DbType=MySql 85 | [sqlserver]: Data Source=127.0.0.1;Initial Catalog=TestDb;Persist Security Info=True;User ID=sa;Password=123456;DbType=SqlServer 86 | [sqlite]: Data Source=testdb.db;DbType=SQLite; // 默认使用App_Data目录 87 | ``` 88 | 89 | > * Framework: 正常的连接字符串,使用ProviderName来区分数据库类型 90 | 91 | 92 | #### 2. Nuget包引用 93 | 94 | ``` 95 | Install-Package Overt.Core.Data -Version 2.2.3 96 | ``` 97 | 98 | 99 | #### 3. 约定 100 | 101 | > * 服务层契约需继承IBaseRepository<> 102 | > * 服务层契约实现实现自定义契约,并继承BaseRepository 103 | > * 外部执行Sql使用 BaseRepository 中 Execute 方法 内部管理连接 104 | 105 | ``` 106 | return await Execute(async (connection) => 107 | { 108 | // 执行方法 109 | }, true); 110 | ``` 111 | 112 | #### 4. 分表实现 113 | 114 | ``` 115 | IBaseRepository的实现 116 | 117 | // 自定义重写TableNameFunc 118 | // 使用GetTableName()可获取到实际的表名 119 | // 内置方法均从上述方法中获取表名,默认表名为实体定义的[Table("主表名")] 120 | public override Func TableNameFunc => () => 121 | { 122 | var tableName = $"{GetMainTableName()}_{DateTime.Now.ToString("yyyyMMdd")}"; 123 | return tableName; 124 | }; 125 | 126 | // 重写创建表的脚本,可在调用过程中,自动创建表,一般用于动态分表 127 | public override Func CreateScriptFunc => (tableName) => 128 | { 129 | return "创建表的Sql脚本"; // 将在增删改操作中执行,查询操作中,表不存在则直接返回空数据 130 | } 131 | ``` 132 | 133 | #### 5. 分库实现 134 | 135 | > * 连接字符串配置中以key - value 模式定义,key使用默认的读写分离关键字【master / secondary】表示写入连接字符串和读取连接字符串 136 | > * 前缀添加 xxx.即可简单定义不同数据库,代码中,对于IBaseRepository的实现,在构造函数中直接常量定义 xxx,如下所示 137 | ``` 138 | using Overt.Core.Data; 139 | using Overt.User.Domain.Contracts; 140 | using Overt.User.Domain.Entities; 141 | using System; 142 | using System.Collections.Generic; 143 | using System.Threading.Tasks; 144 | using Dapper; 145 | using System.Linq; 146 | using Microsoft.Extensions.Configuration; 147 | 148 | namespace Overt.User.Domain.Repositories 149 | { 150 | public class UserRepository : BaseRepository, IUserRepository 151 | { 152 | public UserRepository(IConfiguration configuration) 153 | : base(configuration, "xxx") // dbStoreKey 可用于不同数据库切换,连接字符串key前缀:xxx.master xxx.secondary 154 | { 155 | } 156 | } 157 | } 158 | 159 | ``` 160 | 161 | 162 | #### 6. 事务实现 163 | 164 | > * Framework: 使用TransactionScope 165 | > * DotNetCore: 使用TransactionScope 166 | 167 | ``` 168 | // Service层 169 | public async Task ExecuteInTransactionAsync() 170 | { 171 | // 分布式事务 172 | // 异步中需要增加该参数:TransactionScopeAsyncFlowOption.Enabled 173 | using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) 174 | { 175 | var result = false; 176 | try 177 | { 178 | result = await _userRepository.AddAsync(new UserEntity()); 179 | result &= await _subUserRepository.AddAsync(new SubUserEntity()); 180 | 181 | scope.Complete(); 182 | return result; 183 | } 184 | catch 185 | { 186 | // logger 187 | } 188 | return false; 189 | } 190 | } 191 | ``` 192 | 193 | #### 7. Lambda表达式支持 194 | 195 | > * == 196 | > * ! 197 | > * != 198 | > * null 199 | > * In 200 | > * Equals 201 | > * Contains 202 | > * !Contains 203 | > * StartWith 204 | > * EndWith 205 | > * && 206 | > * || 207 | > * & 208 | > * | 209 | 210 | 211 | ##### 不支持案例 212 | ~~var list = _repository.GetList(1, 1, oo=>"test".Contains(oo.UserName));~~ 213 | ~~var list = _repository.GetList(1, 1, oo=>oo.UserName.IndexOf("abc") > -1);~~ 214 | 215 | 216 | #### 8. 案例使用 217 | 218 | * 添加记录 219 | ``` 220 | // 单条记录插入 221 | _repository.Add(obj); 222 | 223 | // 多条记录批量插入,建议不要超过500条 224 | _repository.Add(obj0, obj1, ...); 225 | ``` 226 | 227 | * 修改记录 228 | ``` 229 | // 修改整份数据 230 | _repository.Set(obj); 231 | 232 | // 修改部分字段(基于字典对象) 233 | var setDic = new Dictionary() 234 | { 235 | { "UserName", "1" } 236 | }; 237 | _repository.Set(() => setDic, oo => oo.UserId == 1); 238 | 239 | // 修改部分字段(基于匿名对象) 240 | var setObj = new 241 | { 242 | UserName = "1" 243 | }; 244 | _repository.Set(() => setObj, oo => oo.UserId == 1); 245 | 246 | // 修改值类型字段进行增减,比如数量的增减,年龄的增减等 247 | _repository.Incr("Age", 1, oo => oo.UserId == 1); 248 | ``` 249 | 250 | * 删除记录 251 | ``` 252 | _repository.Delete(oo => oo.UserId == 1); 253 | ``` 254 | 255 | * 单记录查询 256 | ``` 257 | var entity = _repository.Get(oo => oo.UserId == 1); 258 | ``` 259 | 260 | * 列表记录查询 261 | ``` 262 | var ary = new string[]{ "1", "2" }; 263 | var list = _repository.GetList(1, 1, oo=>ary.Contains(oo.UserId)); 264 | 265 | var ary = new List(){ "1", "2" }; 266 | var list = _repository.GetList(1, 1, oo=>ary.Contains(oo.UserId)); 267 | 268 | var key = "abc"; 269 | var list = _repository.GetList(1, 1, oo=>oo.UserName.Contains(key)); 270 | 271 | var list = _repository.GetList(1, 1, oo=>oo.UserName.Equals(key)); 272 | 273 | var list = _repository.GetList(1, 1, oo=>oo.UserName.Contains("abc")); 274 | 275 | var list = _repository.GetList(1, 1, oo=>oo.UserName.StartWith("abc")); 276 | 277 | var list = _repository.GetList(1, 1, oo=>oo.UserName.EndWith("abc")); 278 | 279 | var list = _repository.GetList(1, 1, oo=>ary.Contains(oo.UserId) && !IsSex); 280 | 281 | var list = _repository.GetList(1, 1, oo=>oo.UserName != null); 282 | 283 | var list = _repository.GetList(1, 1, oo=>oo.UserName == null); 284 | ``` 285 | 286 | 287 | #### 9. 更新说明 288 | 289 | - 2023-02-23 v2.2.3 290 | 291 | > 1. Insert 支持long自增 292 | 293 | 294 | 295 | - 2022-11-22 v2.2.2 296 | 297 | > 1. GetMainTableName开放使用 298 | 299 | 300 | 301 | - 2022-09-29 v2.2.1 302 | 303 | > 1. 增加支持& | 304 | 305 | 306 | 307 | - 2021-12-29 v2.2.0 308 | 309 | > 1. 支持PG数据库 感谢 @liuzhenbao0505 310 | > 2. 修正 StartWith EndWith 的拼接错误 @Zhang-Pengyuan 311 | 312 | 313 | 314 | - 2021-03-26 v2.1.4 315 | 316 | > 1. 将基础方法Execute变更为virtual,可允许重写 317 | 318 | 319 | 320 | - 2021-02-24 v2.1.3 321 | 322 | > 1. 基础方法增加根据某个字段增减数据的方法:IncrAsync(string field, TValue value, Expression> whereExpress) 323 | 324 | 325 | 326 | - 2021-01-14 v2.0.1 327 | 328 | > 1. 修复多数据库情况下并发查询切换数据库导致连接字符串混乱的问题 329 | > 2. Repository层回执SQL脚本的位置调整,防止数据库执行异常无法获知实际的SQL脚本 330 | 331 | 332 | 333 | - 2020-06-30 v2.0.0 334 | 335 | > 1. 升级底层依赖的驱动:Dapper、SqlClient、MySql、SQLite 336 | > 2. 去除原有老版本中使用的Transaction属性,全部统一使用TransactionScope实现事务业务。PS:DotNetCore中的事务只支持单服务器数据,Framework支持分布式数据库!!! 337 | > 3. 如需兼容老版本的的代码,请使用v1.x.x版本的驱动或者代码 338 | 339 | 340 | --- 341 | --------------------------------------------------------------------------------