Giter Site home page Giter Site logo

dotnetcore / smartsql Goto Github PK

View Code? Open in Web Editor NEW
1.0K 80.0 224.0 4.98 MB

SmartSql = MyBatis in C# + .NET Core+ Cache(Memory | Redis) + R/W Splitting + PropertyChangedTrack +Dynamic Repository + InvokeSync + Diagnostics

Home Page: https://smartsql.net/

License: Apache License 2.0

C# 100.00%
orm dotnet-core cross-platform high-performance distributed-computing redis zookeeper read-write-separation cache sql

smartsql's Introduction

SmartSql (Document)

Overview

SmartSql = MyBatis + Cache(Memory | Redis) + R/W Splitting +Dynamic Repository + Diagnostics ......


Simple, efficient, high-performance, scalable, monitoring, progressive development!

How does she work?

SmartSql draws on MyBatis's ideas, uses XML to manage SQL, and provides several filter tags to eliminate various if/else judgment branches at the code level. SmartSql will manage your SQL and filter the tags to maintain your various conditional judgments at the code level to make your code more beautiful.

Why Choose SmartSql?

The Orm,linq of the DotNet system, which is mostly Linq, is very good, eliminating the developer's reliance on SQL. But it ignores the fact that SQL itself is not complex, and that it is difficult for developers to write Linq to generate good performance SQL in complex query scenarios, and I believe that students who have used EF must have this experience: "I think about how SQL writes, and then I write Linq, It's over. You may also want to see what SQL output of Linq is like. " It was a very bad experience. To be absolutely optimized for SQL, developers must have absolute control over SQL. In addition, SQL itself is very simple, why add a layer of translators?

SmartSql has been out of formal open source for more than two years, in the production environment after several micro-service verification. There are also some businesses that are using SmartSql (if you are also using SmartSql Welcome to submit issue)Who is using SmartSql. Has now joined NCC。 The future (Roadmap-2019) SmartSql will continue to add new features to help developers improve efficiency. Welcome to submit Issue https://github.com/dotnetcore/SmartSql/issues.

So why not Dapper, or DbHelper?

Dapper is really good and good performance, but the code that will be ceded to you is filled with SQL and various judgment branches that will make code maintenance difficult to read and maintain. In addition, Dapper only provides DataReader to Entity anti-serialization function. And SmartSql offers a number of features to improve developer efficiency.

Feature Overview

SmartSql

Dynamic Repository

Dynamic Agent Repository (SmartSql.DyRepository) components are SmartSql very unique features that simplify the use of SmartSql. There is little intrusion into the business code. It can be said that using ISqlMapper is the original method, and DyRepository automatically helps you implement these methods.

DyRepository only need to define the Repository interface, through a simple configuration can automatically implement these interfaces and register in the IoC container, when used injection instant acquisition implementation. The principle is to obtain the Scope and SqlId in the XML file of SmartSql through the naming rules of the interface and interface method, use the parameters of the interface method as the Request, and automatically judge the query or perform the operation through the SQL in the XML, and finally realize the ISqlMapper Call.

0. Define Repository interfaces

    public interface IUserRepository : IRepository<User, long>
    {
    }

1. Injection dependencies

            services.AddSmartSql()
                .AddRepositoryFromAssembly(options => { options.AssemblyString = "SmartSql.Starter.Repository"; });

2. Use

    public class UserService
    {
        IUserRepository userRepository;

        public UserService(IUserRepository userRepository)
        {
            this.userRepository = userRepository;
        }
    }

SmartSql Best practices -> SmartCode

SmartCode

By SmartCode Developers simply configure the database connection to build everything that is required for the solution, including, but not limited to:

  • Solution Engineering
  • Give you a restore.
  ReStore:
    Type: Process
    Parameters: 
      FileName: powershell
      WorkingDirectory: '{{Project.Output.Path}}'
      Args: dotnet restore
  • Docker
    • Building Docker Mirroring & Running Instances
 BuildDocker:
    Type: Process
    Parameters:
      FileName: powershell
      WorkingDirectory: '{{Project.Output.Path}}'
      Args: docker build -t {{Project.Parameters.DockerImage}}:v1.0.0 .

  RunDocker:
    Type: Process
    Parameters:
      FileName: powershell
      WorkingDirectory: '{{Project.Output.Path}}'
      Args: docker run --name {{Project.Parameters.DockerImage}} --rm -d -p 8008:80 {{Project.Parameters.DockerImage}}:v1.0.0 .
  • Open a browser by the way
  RunChrome:
    Type: Process
    Parameters:
      FileName: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
      CreateNoWindow: false
      Args: http://localhost:8008/swagger

Docker

SmartCode SmartCode SmartCode SmartCode

Directory structure generated by SmartCode

SmartCode-directory-structure

Read and write separation

SmartSql Read and write separation is especially easy, just provide a good configuration can be:

  <Database>
    <DbProvider Name="PostgreSql"/>
    <Write Name="WriteDB" ConnectionString="${Master}"/>
    <Read Name="ReadDb-1" ConnectionString="${Slave-0}" Weight="100"/>
    <Read Name="ReadDb-2" ConnectionString="${Slave-1}" Weight="100"/>
  </Database>

Cache

  • Lru Least recently used algorithms
  • Fifo Advanced first-out algorithm
  • RedisCacheProvider
  • Other inherited self-ICacheProvider cache types are available
<Caches>
    <Cache Id="LruCache" Type="Lru">
      <Property Name="CacheSize" Value="10"/>
      <FlushOnExecute Statement="AllPrimitive.Insert"/>
      <FlushInterval Hours="1" Minutes="0" Seconds="0"/>
    </Cache>
    <Cache Id="FifoCache" Type="Fifo">
      <Property Name="CacheSize" Value="10"/>
    </Cache>
    <Cache Id="RedisCache" Type="${RedisCacheProvider}">
      <Property Name="ConnectionString" Value="${Redis}" />
      <FlushInterval Seconds="60"/>
    </Cache>
  </Caches>
   <Statement Id="QueryByLruCache"  Cache="LruCache">
      SELECT Top 6 T.* From T_User T;
    </Statement>

Type Handler

The SmartSql is implemented internally DotNet the main types of type handlers, and some types of compatible type conversion processors are provided, as well as more commonly used JsonTypeHanlder.

    <TypeHandler PropertyType="SmartSql.Test.Entities.UserInfo,SmartSql.Test" Type="${JsonTypeHandler`}">
      <Properties>
        <Property Name="DateFormat" Value="yyyy-MM-dd mm:ss"/>
        <Property Name="NamingStrategy" Value="Camel"/>
      </Properties>
    </TypeHandler>

CUD Code generation

SmartSql also provides CUD extension functions to help developers generate good CUD-SQL for direct developer use without having to write any configuration.

public static TEntity GetById<TEntity, TPrimaryKey>(this ISqlMapper);
public static TPrimaryKey Insert<TEntity, TPrimaryKey>(this ISqlMapper sqlMapper, TEntity entity);
public static int DyUpdate<TEntity>(this ISqlMapper sqlMapper, object entity);
public static int Update<TEntity>(this ISqlMapper sqlMapper, TEntity entity);
public static int DeleteById<TEntity, TPrimaryKey>(this ISqlMapper sqlMapper, TPrimaryKey id);
public static int DeleteMany<TEntity, TPrimaryKey>(this ISqlMapper sqlMapper, IEnumerable<TPrimaryKey> ids);

Id Generator

SnowflakeId

<IdGenerators>
    <IdGenerator Name="SnowflakeId" Type="SnowflakeId">
      <Properties>
        <Property Name="WorkerIdBits" Value="10"/>
        <Property Name="WorkerId" Value="888"/>
        <Property Name="Sequence" Value="1"/>
      </Properties>
    </IdGenerator>
</IdGenerators>
    <Statement Id="Insert">
      <IdGenerator Name="SnowflakeId" Id="Id"/>
      INSERT INTO T_UseIdGenEntity
      (
      Id,
      Name
      )
      VALUES
      (
      @Id,
      @Name
      );
      Select @Id;
    </Statement>
var id = SqlMapper.ExecuteScalar<long>(new RequestContext
            {
                Scope = nameof(UseIdGenEntity),
                SqlId = "Insert",
                Request = new UseIdGenEntity()
                {
                    Name = "SmartSql"
                }
            });

DbSequence

<IdGenerators>
    <IdGenerator Name="DbSequence" Type="DbSequence">
      <Properties>
        <Property Name="Step" Value="10"/>
        <Property Name="SequenceSql" Value="Select Next Value For IdSequence;"/>
      </Properties>
    </IdGenerator>
</IdGenerators>
    <Statement Id="InsertByDbSequence">
      <IdGenerator Name="DbSequence" Id="Id"/>
      INSERT INTO T_UseIdGenEntity
      (
      Id,
      Name
      )
      VALUES
      (
      @Id,
      @Name
      );
      Select @Id;
    </Statement>
            var id = SqlMapper.ExecuteScalar<long>(new RequestContext
            {
                Scope = nameof(UseIdGenEntity),
                SqlId = "InsertByDbSequence",
                Request = new UseIdGenEntity()
                {
                    Name = "SmartSql"
                }
            });

AOP Transaction

        [Transaction]
        public virtual long AddWithTran(User user)
        {
            return _userRepository.Insert(user);
        }

Transaction nesting

When a transaction is nested, the transaction attribute annotation of the child function is no longer turned on, and the transaction that calls the function by the parent is used instead

        [Transaction]
        public virtual long AddWithTranWrap(User user)
        {
            return AddWithTran(user);
        }

BulkInsert

using (var dbSession= SqlMapper.SessionStore.Open())
            {
                var data = SqlMapper.GetDataTable(new RequestContext
                {
                    Scope = nameof(AllPrimitive),
                    SqlId = "Query",
                    Request = new { Taken = 100 }
                });
                data.TableName = "T_AllPrimitive";
                IBulkInsert bulkInsert = new BulkInsert(dbSession);
                bulkInsert.Table = data;
                bulkInsert.Insert();
            }

Skywalking Monitoring

SmartSql currently supports Skywalking monitoring and is enabled by installing the SkyAPM-dotnet agent. The following is a partial screenshot.

Monitoring execution commands

Query

View whether the cache is cached and the number of records returned

Query-Detail

View executed SQL statements

Query-Statement

Transaction

Transaction

Error

Error

Exception stack Trace

Error-Detail

Nuget Packages

Package NuGet Stable Downloads
SmartSql SmartSql SmartSql
SmartSql.Schema SmartSql.Schema SmartSql.Schema
SmartSql.TypeHandler SmartSql.TypeHandler SmartSql.TypeHandler
SmartSql.DyRepository SmartSql.DyRepository SmartSql.DyRepository
SmartSql.DIExtension SmartSql.DIExtension SmartSql.DIExtension
SmartSql.Cache.Redis SmartSql.Cache.Redis SmartSql.Cache.Redis
SmartSql.ScriptTag SmartSql.ScriptTag SmartSql.ScriptTag
SmartSql.AOP SmartSql.AOP SmartSql.AOP
SmartSql.Options SmartSql.Options SmartSql.Options
SmartSql.Bulk SmartSql.Bulk SmartSql.Bulk
SmartSql.Bulk.SqlServer SmartSql.Bulk.SqlServer SmartSql.Bulk.SqlServer
SmartSql.Bulk.MsSqlServer SmartSql.Bulk.MsSqlServer SmartSql.Bulk.MsSqlServer
SmartSql.Bulk.PostgreSql SmartSql.Bulk.PostgreSql SmartSql.Bulk.PostgreSql
SmartSql.Bulk.MySql SmartSql.Bulk.MySql SmartSql.Bulk.MySql
SmartSql.Bulk.MySqlConnector SmartSql.Bulk.MySqlConnector SmartSql.Bulk.MySqlConnector
SmartSql.InvokeSync SmartSql.InvokeSync SmartSql.InvokeSync
SmartSql.InvokeSync.Kafka SmartSql.InvokeSync.Kafka SmartSql.InvokeSync.Kafka
SmartSql.InvokeSync.RabbitMQ SmartSql.InvokeSync.RabbitMQ SmartSql.InvokeSync.RabbitMQ

Demo

SmartSql.Sample.AspNetCore

QQGroup

Click on the link to join the QQ group [SmartSql official QQ group]:604762592

smartsql's People

Contributors

ahoo-wang avatar dependabot[bot] avatar elderjames avatar gmij avatar ktdynamic avatar lp9937 avatar noahjzc avatar renovate[bot] avatar rocherkong avatar xiangxiren avatar xiaoheitu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

smartsql's Issues

强制传参对象匹配后不能为null

比如在批量删除场景下,我们需要多条件删除,如果传参对象在QueryParams均未匹配到,那么将会直接把整个表给清空

Delete From test _testService.Delete(new{xxid=1});

如果xxid没有在QueryParams中匹配到,test表里面的数据将全部被删除

SmartSql-V4 意见征集

SmartSql-V4 意见征集

目标

简洁、高效、扩展性、可观测

计划

  1. 执行流重构(管道-中间件模式)
  2. 动态类型转换重构
  3. DataReader 反序列化Emit重构
  4. Statement 预编译 进一步压榨性能
  5. 自定义标签支持
  6. CUD 自动实现
  7. 动态代理仓储重构
  8. 表达式支持(SmartExpression
  9. 性能监控
  10. 自定义中间件
  11. 最小化可运行环境(only DataSource)

SmartSql-V4 recommends collecting

Goal

Simplicity, efficiency, scalability, monitoring

Plan

  1. Perform flow refactoring (pipeline-middleware mode)
  2. Dynamic Type Transformation Refactoring
  3. DataReader Reverse Serialization reconstruction
  4. Statement pre-compilation further squeezing performance
  5. Custom Tag Support
  6. CUD Automatic Implementation
  7. Dynamic Proxy Repository reconstruction
  8. Expression Support (SmartexEression)
  9. Performance monitoring
  10. Custom Middleware
  11. Minimize the operating environment (only DataSource)

事务中执行多条语句,提示 The connection does not support MultipleActiveResultSets。

  1. 找不到MultipleActiveResultSets的示例,不知道怎么写。
  2. 可能是MultipleResultMaps?那么我的三条语句分布在三个xml里,写到哪里呢?

代码:

        public async Task<int> InsertAsync(ArticleUpdateParameter parameter)
        {
            try
            {
                _mapper.BeginTransaction();

                var id = await ArticleRepository.InsertAsync(parameter);
                var categoryTask = CategoryRepository.SetArticleCategoriesAsync(articleId, categories);
                var tagTask = TagRepository.SetArticleTagsAsync(articleId, tags);
                await Task.WhenAll(categoryTask, tagTask);

                _mapper.CommitTransaction();
                return id;
            }
            catch (Exception)
            {
                _mapper.RollbackTransaction();
                throw;
            }
        }

日志:

dbug: SmartSql.SmartSqlMapper[0]
      BeginTransaction DbSession.Id:11970789-3f5f-413d-be61-b1baad9c1285
dbug: SmartSql.Command.PreparedCommand[0]
      PreparedCommand.Prepare->Statement.Id:[Article.Insert],Sql:
      INSERT INTO Article
            (
            Cover,
            Author,
            Title,
            Content,
            Digest,
            ViewCount,
            CommentCount,
            UpdatedAt,
            CreatedAt,
            IsDeleted,
            Remark
            )
            VALUES
            (
            @Cover,
            @Author,
            @Title,
            @Content,
            @Digest,
            default,
            default,
            @UpdatedAt,
            @CreatedAt,
            default,
            @Remark
            )
            ;Select Scope_Identity();
      Parameters:[Cover=assets/img/write-bg.jpg,Author=1,Title=这是标题,Content=---
title: 这是标题
date: 2018-12-03 00:00
categories:
- 分类1
- 分类2
tags:
  - 标签1
  - 标签2
---

这是内容,Digest=,UpdatedAt=2019/4/1 22:11:23,CreatedAt=2018/12/3 0:00:00,Remark=]
      Sql with parameter value:
      INSERT INTO Article
            (
            Cover,
            Author,
            Title,
            Content,
            Digest,
            ViewCount,
            CommentCount,
            UpdatedAt,
            CreatedAt,
            IsDeleted,
            Remark
            )
            VALUES
            (
            'assets/img/write-bg.jpg',
            1,
            '这是标题',
            '---
title: 这是标题
date: 2018-12-03 00:00
categories:
- 分类1
- 分类2
tags:
  - 标签1
  - 标签2
---

这是内容',
            NULL,
            default,
            default,
            '2019/4/1 22:11:23',
            '2018/12/3 0:00:00',
            default,
            NULL
            )
            ;Select Scope_Identity();
warn: SmartSql.Command.PreparedCommand[0]
      PreparedCommand.Prepare:StatementKey:Category.SetArticleCategories:can not find ParamterName:names!
warn: SmartSql.Command.PreparedCommand[0]
      PreparedCommand.Prepare:StatementKey:Category.SetArticleCategories:can not find ParamterName:names!
warn: SmartSql.Command.PreparedCommand[0]
      PreparedCommand.Prepare:StatementKey:Category.SetArticleCategories:can not find ParamterName:names!
warn: SmartSql.Command.PreparedCommand[0]
      PreparedCommand.Prepare:StatementKey:Category.SetArticleCategories:can not find ParamterName:names!
dbug: SmartSql.Command.PreparedCommand[0]
      PreparedCommand.Prepare->Statement.Id:[Category.SetArticleCategories],Sql:
      declare @names table ([name] nvarchar(30))
              insert into @names values
              (@T_For__categories_0)
             ,
              (@T_For__categories_1)


            -- insert only not exists in Category table
            insert INTO Category
            select name, getdate(), getdate(), null, 0 from
            (select name from @names where name not in (select name from Category)) T

            -- rebuild middle-table related data
            delete from ArticleCategories where Article = @articleId
            insert into ArticleCategories select @articleId, Id, getdate(), getdate() from
              (select id from Category where Name in (select name from @names)) T;
            select 1;
      Parameters:[T_For__categories_0=分类1,T_For__categories_1=分类2,articleId=45]
      Sql with parameter value:
      declare @names table ([name] nvarchar(30))
              insert into @names values
              ('分类1')
             ,
              ('分类2')


            -- insert only not exists in Category table
            insert INTO Category
            select name, getdate(), getdate(), null, 0 from
            (select name from @names where name not in (select name from Category)) T

            -- rebuild middle-table related data
            delete from ArticleCategories where Article = 45
            insert into ArticleCategories select 45, Id, getdate(), getdate() from
              (select id from Category where Name in (select name from @names)) T;
            select 1;
warn: SmartSql.Command.PreparedCommand[0]
      PreparedCommand.Prepare:StatementKey:Tag.SetArticleTags:can not find ParamterName:names!
warn: SmartSql.Command.PreparedCommand[0]
      PreparedCommand.Prepare:StatementKey:Tag.SetArticleTags:can not find ParamterName:names!
warn: SmartSql.Command.PreparedCommand[0]
      PreparedCommand.Prepare:StatementKey:Tag.SetArticleTags:can not find ParamterName:names!
warn: SmartSql.Command.PreparedCommand[0]
      PreparedCommand.Prepare:StatementKey:Tag.SetArticleTags:can not find ParamterName:names!
dbug: SmartSql.Command.PreparedCommand[0]
      PreparedCommand.Prepare->Statement.Id:[Tag.SetArticleTags],Sql:
      declare @names table ([name] nvarchar(30))
              insert into @names values
              (@T_For__tags_0)
             ,
              (@T_For__tags_1)


            -- insert only not exists in Tag table
            insert INTO Tag
            select name, getdate(), getdate(), null, 0 from
            (select name from @names where name not in (select name from Tag)) T

            -- rebuild middle-table related data
            delete from ArticleTags where Article = @articleId
            insert into ArticleTags select @articleId, Id, getdate(), getdate() from
              (select id from Tag where Name in (select name from @names)) T;
            select 1;
      Parameters:[T_For__tags_0=标签1,T_For__tags_1=标签2,articleId=45]
      Sql with parameter value:
      declare @names table ([name] nvarchar(30))
              insert into @names values
              ('标签1')
             ,
              ('标签2')


            -- insert only not exists in Tag table
            insert INTO Tag
            select name, getdate(), getdate(), null, 0 from
            (select name from @names where name not in (select name from Tag)) T

            -- rebuild middle-table related data
            delete from ArticleTags where Article = 45
            insert into ArticleTags select 45, Id, getdate(), getdate() from
              (select id from Tag where Name in (select name from @names)) T;
            select 1;
fail: SmartSql.SmartSqlMapper[0]
      [null]
dbug: SmartSql.SmartSqlMapper[0]
      RollbackTransaction DbSession.Id:11970789-3f5f-413d-be61-b1baad9c1285
dbug: SmartSql.DbSession.DbConnectionSession[0]
      RollbackTransaction .
dbug: SmartSql.DbSession.DbConnectionSession[0]
      CloseConnection 39184750:WriteDB
dbug: SmartSql.DbSession.DbConnectionSession[0]
      Dispose.
fail: Blog.API.Filters.GlobalExceptionFilter[-2146233079]
      The connection does not support MultipleActiveResultSets.
System.InvalidOperationException: The connection does not support MultipleActiveResultSets.
   at SmartSql.SmartSqlMapper.<>c__DisplayClass42_0`1.<<ExecuteWrapAsync>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at SmartSql.SmartSqlMapper.WrapWithTransactionAsync[T](RequestContext context, Func`2 executeFun)
   at SmartSql.SmartSqlMapper.ExecuteWrapAsync[T](Func`2 execute, RequestContext context, DataSourceChoice sourceChoice)
   at SmartSql.SmartSqlMapper.ExecuteScalarAsync[T](RequestContext context)
   at Blog.Service.ArticleService.InsertAsync(ArticleUpdateParameter parameter) in F:\Projects\siegrain.blog\Blog.Service\ArticleService.cs:line 39
   at Blog.API.Controllers.ArticleController.Insert(ArticleUpdateParameter parameter) in F:\Projects\siegrain.blog\Blog.API\Controllers\ArticleController.cs:line 36
   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync()

Is it good idea?

I am sure you understand that it is incorrect in the common case

INSERT INTO T_Test (Name) VALUES (@name) **;Select @@IDENTITY**

xml 逻辑判断语句优化

//java --mybatis

<foreach collection="array" open="(" close=")" separator="," item="ids">
            #{ids}
</foreach>

 <update id="updateStudent" parameterType="map" >
        update students
        <set>
            <if test="pname!=null">
                name = #{pname},
            </if>

            <if test="psal!=null">
                sal = #{psal},
            </if>
        </set>
        where id = #{pid}
    </update>

 <trim suffixOverrides=",">
        <if test="id!=null">
            id,
        </if>

        <if test="name!=null">
            name,
        </if>

        <if test="sal!=null">
            sal,
        </if>
      </trim>

  <where>
            <if test="pid!=null" >
                and id = #{pid}    
            </if>

            <if test="pname!=null" >
                and name = #{pname}
            </if>

            <if test="psal!=null" >
                and sal = #{psal}
            </if>
        </where>

SmartSql-Roadmap-2019

SmartSql Roadmap - 2019

Simplicity, efficiency, performance, scalability, monitoring, progressive development


简洁、高效、性能、扩展性、监控、渐进式开发

Q2 - SmartSql-V4

  • Execute flow refactoring (pipeline-middleware mode)
  • Increase unit Test coverage
  • Increase performance test report granularity and coverage
  • IDataReaderDeserializer
    • DictionaryDeserializer
    • DynamicDeserializer
    • EntityDeserializer
    • MultipleResultDeserializer
    • ValueTypeDeserializer
  • Custom Tags
    • Script Tag
  • TypeHandler refactoring
  • CUD Auto Implementation (configuration Entity.tablename required)
  • Dynamic Prxy Repository Refactoring
  • Multi-configuration Source loader support
    • XmlConfigLoader
      • File
      • Embedded
    • JsonConfigLoader
    • ZookeeperConfigLoader
    • ConsulConfigLoader
  • Minimize the running environment(only DataSource)
  • Distributed Cache Refactoring
  • Diagnostics support
    • Cache
    • PreparedStatement
    • CommandExecuter
    • Deserializer
    • ERROR
  • DI Use experience optimization
  • SmartSql.Batch -> SmartSql.Bulk
  • IdGenerator

  • 执行流重构(管道-中间件模式)
  • 增加单元测试覆盖率
  • 增加性能测试报告粒度与覆盖率
  • IDataReaderDeserializer
    • DictionaryDeserializer
    • DynamicDeserializer
    • EntityDeserializer
    • MultipleResultDeserializer
    • ValueTypeDeserializer
  • 自定义标签
    • Script Tag
  • TypeHandler 重构
  • CUD 自动实现 (需配置Entity.TableName)
  • 动态代理仓储重构
  • 多配置源加载器支持
    • XmlConfigLoader
      • File
      • Embedded
    • JsonConfigLoader
    • ZookeeperConfigLoader
    • ConsulConfigLoader
  • 最小化可运行环境(only DataSource)
  • 分布式缓存重构
  • Diagnostics 支持
    • Cache
    • PreparedStatement
    • CommandExecuter
    • Deserializer
    • ERROR
  • DI 使用体验优化
  • SmartSql.Batch -> SmartSql.Bulk
  • IdGenerator

Q3


Q4

  • SmartSql.Monitor
    • Authorized
    • Performance
    • Fault Tracking
    • Call Trace
    • Dynamic configuration
    • UI
    • Storage
      • InMemory
      • ...

  • SmartSql.Monitor
    • 授权
    • 性能监控
    • 故障跟踪
    • 调用跟踪
    • 动态配置
    • UI
    • 存储
      • InMemory
      • ...

SmartSql-v3.0 意见收集

SmartSql-v3.0 意见收集

v3.0 已知主要目标:

  1. 增强SmartSql扩展性
  2. 重构部分代码
  3. 去除Dapper依赖
  4. 优化缓存触发策略
  5. 仓储接口动态实现
  6. 以及各位的意见,请在此Issue中评论新增意见

SmartSql 的成长离不开大家的意见&建议,感谢各位对SmartSql的支持!

batch insert

请问批量添加功能如何实现呢,我参照文档的 这样子的写法,这样子会有异常抛出,提示For 的Key 键不能为空!

INSERT INTO T_Test
(Name,Status)
VALUES

(@name,@Status)


我觉得批量添加在开发中还是会经常用到,比方说做Excel导入时,订单项添加时,都会用到批量添加,希望作者能够写一些示例。我查阅了SmartSqlStarter项目,内容较少也没有涉及到批量操作的功能。
Thanks

分表操作

对于分表的操作,(切换表名)貌似不是很友好?请赐教

特性请求:增加配置api,替换SmartSqlMapConfig

尽量使用.NET Core项目的配置文件,这样更符合使用习惯,而且能减少维护一个配置文件。

  1. 数据库连接,使用默认的ConnectionStrings中的配置项,便于与Dapper原来的共用。
  2. ADO.NET数据库类型通过IDbConnection的实例来判断。
  3. 组件可以新增通过配置api,在IoC注册时替换。

多层实体访问

class User
{
    public string Name {get; set;}
    public int Age { get; set; }
    public Address Address {get; set;}
}

class Address
{
    public string Province {get;set;}

    public string City { get; set; }
}


public interface IUserRepository
{
    public int Insert(User user);
}

   <Statement Id="Insert">
        Insert INTO User(Name,Age)VALUES(@Name,@Age);
       <Spread Property="Address">
        Insert INTO Address(Province,City)VALUES(@Province,@City);
       </Spread>
   </Statement>

一次查询结果映射到多层实体

查询结果里一部分字段映射到一个实体,另一部分映射到这个实体里的实体。
另外考虑一对多联表查询映射到实体里集合的场景。

Who is using SmartSql (谁在使用SmartSql)

Who is using SmartSql

Pls. submit a comment in this issue,You can refer to the following sample answer for the format:

  • Orgnizatioin: Maidao sensing technology (Shanghai) Co., Ltd.
  • Location: Shanghai, China
  • Website : www.51mydao.com

谁在使用SmartSql

在此提交一条评论, 您可以参考下面的样例来提供您的信息:

  • 组织 : 买道传感科技(上海)有限公司
  • 地址: **上海
  • 网址 : www.51mydao.com

Statement 增加配置连接数据库的database="WriteDB"配置的数据库连接

` 一台写数据库服务器 部署一个sql server数据库实例里面部署了4个数据库(产品数据库、用户数据库、 仓库数据库、订单数据库)
N台查询数据库服务器 每台部署的数据库都和写数据库服务器的一样,都是一个sql server 实例和四个数据库(产品数据库、用户数据库、 仓库数据库、订单数据库)表结构等都是一样的,只是用来查询的,当然写和查的数据库数据怎么同步系统不用管。
当初也是有严格的规范的,比如四个数据库的应用必须独立,系统的数据调用必须用调用各自的api,数据库之间不能相互关联查询等,但是现实问题是遇到性能问题,后来都不执行了。
根据我对框架的了解,如果是不同的数据库比如mysql和sql server这种情况的多数据库支持最好的方式就是建立仓储
但是是同一个sql server 有多个数据库的,我的这种场景请问你的框架怎么支持,四个数据库用四个仓储实现,分别配置各自的读和写,而且有时候在特殊场景下会出现多个数据库之间相互关联查询 (个人意见也许不适应你的规范,但是个人认为这种情况不一定一定要去建立四个仓储)
在实际部署的时候,我们以前的场景是比如写数据库部署一台服务器(四个数据库),北京部署一台查询数据库服务器 (四个数据库),上海部署一台查询数据库服务器(四个数据库), 我们的部署是这样的Server端和Web端,数据库部署一台服务器,server部署一台服务器,web部署一台服务器。 数据库服务器的访问是通过server服务器访问,web服务器访问server服务器;web端是有负载均衡的,在部署的时候就已经把server端访问那个数据库配置设置好了,也是就server访问那个查询数据库都已经是配置好的,web端访问那个server端也是之前就配置好的(而且这种部署一般只是是两个通道,一个通道有问题就可以切换到另外一个通道),所有北京的用户访问北京的,上海的访问上海的,具体怎么判断北京和上海不是目前系统关心的。请问你的目前的这个如果要手工配置指定,只能用你的策略,如果要手工配置就不行,这种情况下 多个服务器的数据库 有读和写 每个都是多个数据库这么支持

根据我对框架的了解,其实目前框架底层本身是支持的,而且做个小改动就完全可以支持我提出的场景:
1 修改以下配置的地方就可以做到
<DbProvider Name="MySqlClientFactory" ParameterPrefix="?" Type="MySql.Data.MySqlClient.MySqlClientFactory,MySqlConnector"/> <Write Name="WriteDB" ConnectionString="Data Source=pc;database=server;uid=root;pwd=111;CharSet=utf8;AllowUserVariables=True"/> <Read Name="ReadDB-1" ConnectionString="Data Source=pc;database=server;uid=root;pwd=111;CharSet=utf8;AllowUserVariables=True" Weight="1" />

这里的配置可以有多个写和多个读,或者这里不区分读或者写,只是多个数据库连接,至于那个是读和写用户自己知道,用户自己在开发的方法中根据实际情况配置那个数据库连接即可
2、 在Statement 增加一个配置项目 database="数据库连接" 这个数据库连接就是这个 <Write Name="WriteDB" ConnectionString="Data Source=pc;database=server;uid=root;pwd=111;CharSet=utf8;AllowUserVariables=True"/> 的 name <Statement Id="Insert" database="WriteDB"> `

希望能支持java那种已接口形式调用

//接口
public interface IAMapper<T> {
           int findPageCount(T t);
           .....
}
//mybatis.xml
<select id="findPageCount" resultType="java.lang.Integer"  parameterType="Object">
		select count(1) from merchant_info
		<include refid="Example_Where_Clause"/>
</select>
没有实现IAMapper接口的类,可以直接通过
@Service
public class AImpl implements IAService{
@Autowired
private IAMapper<A> AMapper;
 public int findPageCount(A a) {
        return AMapper.findPageCount(a);
    }
}

动态多字段排序

传入一个字典,Key是字段,OrderType是排序类型。

    public Dictionary<string, OrderType> OrderBy { get; set; }

    public enum OrderType
    {
        Asc,
        Desc,
    }

可以让For标签支持字典,取出Key和Value,并可以分别传入Switch标签。

Statement <Include RefId="QueryParams" />修改xml文件后,报空指针

在程序调试期间修改XML文件,再执行相关查询会报空指针信息(查询数据相关方法)。如下:

at SmartSql.Configuration.Tags.Include.BuildSql(RequestContext context)
at SmartSql.Configuration.Statements.Statement.BuildSql(RequestContext context)
at SmartSql.SqlBuilder.BuildSql(RequestContext context)
at SmartSql.SmartSqlMapper.SetupRequestContext(RequestContext context, DataSourceChoice sourceChoice)
at SmartSql.SmartSqlMapper.ExecuteWrap[T](Func`2 execute, RequestContext context, DataSourceChoice sourceChoice)
at SmartSql.SmartSqlMapper.Query[T](RequestContext context)
【project infomation hidden】
at lambda_method(Closure , Object , Object[] )
at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync()

增加批量新增,修改功能

1 批量新增功能 全部新增
2 批量更新功能 全部更新
3 同时用新增和更新功能,根据是否数据库已经存在记录 存在的更新 不存在的新增
(注:更新是有参数设置每批次的条数,比如一次更新100万条 这种数据太大,可以分为数据块 比如每批次5000条执行一次sql脚本)
mysql有批量新增更新语法 比较好用,虽然sql server也有批量功能单不如mysql强大 ,可以参考这个组件http://bulk-operations.net/

MultipleResultMap 增强,支持实体嵌套

例如有两张表,一个是Hotel,一个是Room,还有一个User,需要把Hotel的一行记录映射到一个Hotel的实体,而把这个HotelId关联的Room记录映射到Hotel实体的一个集合属性上,User一个映射到Hotel中的实体属性上。

public class Hotel
{
   public int HotelId {get;set;}
   public string Name {get;set;}
   public string Address{get;set;}
   public string Phone {get;set;}
   public List<Room> Rooms {get;set;}
   public User Master {get;set;}
}

能否简化下SmartSqlMapConfig.xml的配置?

能否简化下SmartSqlMapConfig.xml的xml配置?:

<SmartSqlMap Path="Maps/T_Test.xml"></SmartSqlMap>

此处能否修改为

<SmartSqlMap Path="Maps/"></SmartSqlMap>

直接以文件夹的形式提供配置项?

接口上的 Transaction 特性无效

在虚方法上这个特性有效,在接口方法上无效:
请问是不支持接口吗?

有效示例:

[Transaction]
public virtual async Task<bool> UpdateAsync(ArticleUpdateParameter parameter)
{
     var externalTask = SetArticleTagsAndCategories(parameter.Id, parameter.Tags, parameter.Categories);
     var updateTask = ArticleRepository.UpdateAsync(parameter);
     await Task.WhenAll(externalTask, updateTask);
     return true;
}

image

无效示例:

[Transaction]
Task<int> DeleteAsync(int id);

image

增加嵌套实体的多sql多表更新功能,并默认使用事务

主要用于有“实体内直接引用实体”模型的聚合的整体更新。这种类型的模型在DDD中普遍存在,而且聚合内强一致性,需要使用事务更新, 希望DyRepository中可以实现。

仓储方法实现多实体参数和嵌套实体,xml中支持多语句事务执行。这在联表更新非常有用!

AOP事务判断事务状态

在主方法和子方法都存在TransactionAttribute 的情况下。会出异常。AspectCore.DynamicProxy.AspectInvocationException: Exception has been thrown by the aspect of an invocation. ---> Before RollbackTransaction,Please BeginTransaction first!. ---> SmartSql.Exceptions.SmartSqlException: Before RollbackTransaction,Please BeginTransaction first!

如果能在 Invoke 里面判断一下当前事务状态话,在事务已经Begin之后就不要再操作事务了。这样应该可以解决这个问题。

Better documentation

Good, but it would be better with very good documentation, all English, full samples with source code, and many samples.

Can I call stored procedure using SmartSql ?

Great

Redis配置

1.提取到Config统一配置Connection;
2.可加入环境变量配置

建议能支持返回DataSet和Table

有些业务需要返回多个结果集,比如返回数据和查询条件下的条数,这个sql语句是一个存储过程,里面需要处理逻辑;或者有些大数据需要处理,但是数据是多个表,需要一次返回数据 如果用DataSet就非常方便

【Feature Request】DyRepository实现一个方法中进行多次查询并映射到返回实体的不同属性

鉴于最新版本已支持多查询返回多个对象,现在提议一个特性,就是在DyRepository中的方法执行多条查询时,可以把多个结果映射到一个实体的不同属性上。

例如返回类型是以下类型:

    public class PagedData<TRecord>
    {
        public PagedData()
        {
        }

        public PagedData(int pageSize, int pageNow)
        {
            PageSize = pageSize;
            PageNow = pageNow;
            TotalCount = 0;
            Records = Enumerable.Empty<TRecord>();
        }

        public int PageSize { get; set; }

        public int PageNow { get; set; }

        public int TotalCount { get; set; }

        public IEnumerable<TRecord> Records { get; set; }
    }

那么会进行两次查询:

  1. 先查询总记录数,结果映射到TotalCount上
  2. 再查询分页的记录,结果映射到Records 上

新版本意见

1.去除缓存功能,提高性能,java中的mybatis,很多人操作缓存还是放在service层,有自定义的规则,或者微服务中,有服务接口缓存,
2.xml标签简单化,建议按照新的java中mybatis中的标签来设计,比如 等等
3.按照规则,来调用sqlmapper,而不是大量重复代码,比如
SqlMapper.ExecuteScalar(new RequestContext
{
Scope = "T_Test",
SqlId = "Insert",
Request = new { Name = $"Name-{preId}", TableName = "T_Test1" }
});
Scope, SqlId 通过规则可以封装scope sqlid,只需传入参数即可,参数类型

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.