Skip to content

Commit a5e4d55

Browse files
committed
1. added support Root for MultipleResultMap
2. added support ReadDb for Statement 3. optimized PreparedCommand.Prepare log output
1 parent d1f45a8 commit a5e4d55

File tree

11 files changed

+129
-56
lines changed

11 files changed

+129
-56
lines changed

doc/Schemas/SmartSqlMap.xsd

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,8 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<xs:schema
3-
attributeFormDefault="unqualified"
4-
elementFormDefault="qualified"
5-
targetNamespace="http://SmartSql.net/schemas/SmartSqlMap.xsd"
6-
xmlns:xs="http://www.w3.org/2001/XMLSchema"
7-
xmlns="http://SmartSql.net/schemas/SmartSqlMap.xsd"
8-
xmlns:vs="http://schemas.microsoft.com/Visual-Studio-Intellisense"
9-
vs:friendlyname="SmartSqlMap Configuration Schema"
10-
vs:ishtmlschema="false"
11-
vs:iscasesensitive="true"
12-
vs:requireattributequotes="true"
13-
vs:defaultnamespacequalifier=""
14-
vs:defaultnsprefix=""
15-
>
2+
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://SmartSql.net/schemas/SmartSqlMap.xsd"
3+
xmlns:xs="http://www.w3.org/2001/XMLSchema"
4+
xmlns="http://SmartSql.net/schemas/SmartSqlMap.xsd"
5+
xmlns:vs="http://schemas.microsoft.com/Visual-Studio-Intellisense" vs:friendlyname="SmartSqlMap Configuration Schema" vs:ishtmlschema="false" vs:iscasesensitive="true" vs:requireattributequotes="true" vs:defaultnamespacequalifier="" vs:defaultnsprefix="">
166

177
<xs:simpleType name="CSharpType">
188
<xs:restriction base="xs:NMTOKEN">
@@ -71,7 +61,7 @@
7161
</xs:element>
7262
</xs:choice>
7363
<xs:attribute name="Id" type="xs:string" use="required" />
74-
<xs:attribute name="Type" use="required" >
64+
<xs:attribute name="Type" use="required">
7565
<xs:simpleType>
7666
<xs:restriction base="xs:NMTOKEN">
7767
<xs:enumeration value="Lru"/>
@@ -121,7 +111,7 @@
121111
<xs:complexType>
122112
<xs:sequence>
123113
<xs:element ref="Constructor" maxOccurs="1" minOccurs="0"></xs:element>
124-
<xs:element ref="Result" maxOccurs="unbounded" minOccurs="0"/>
114+
<xs:element ref="Result" maxOccurs="unbounded" minOccurs="0"/>
125115
</xs:sequence>
126116
<xs:attribute name="Id" type="xs:string" use="required" />
127117
</xs:complexType>
@@ -152,9 +142,13 @@
152142
<xs:element name="MultipleResultMap" minOccurs="0" maxOccurs="unbounded">
153143
<xs:complexType>
154144
<xs:sequence>
145+
<xs:element maxOccurs="1" minOccurs="0" name="Root">
146+
<xs:complexType>
147+
<xs:attribute name="MapId" type="xs:string" use="optional" />
148+
</xs:complexType>
149+
</xs:element>
155150
<xs:element maxOccurs="unbounded" name="Result">
156151
<xs:complexType>
157-
<xs:attribute name="Index" type="xs:unsignedByte" use="optional" />
158152
<xs:attribute name="Property" type="xs:string" use="optional" />
159153
<xs:attribute name="MapId" type="xs:string" use="optional" />
160154
</xs:complexType>
@@ -228,8 +222,8 @@
228222
<xs:element name="Switch">
229223
<xs:complexType mixed="true">
230224
<xs:sequence minOccurs="1">
231-
<xs:element ref="Case" minOccurs="0" maxOccurs="unbounded"/>
232-
<xs:element ref="Default" minOccurs="0" maxOccurs="1"/>
225+
<xs:element ref="Case" minOccurs="0" maxOccurs="unbounded"/>
226+
<xs:element ref="Default" minOccurs="0" maxOccurs="1"/>
233227
</xs:sequence>
234228
<xs:attribute name="Prepend" type="xs:string" use="optional" />
235229
<xs:attribute name="Property" type="xs:string" use="required" />
@@ -693,7 +687,7 @@
693687
</xs:element>
694688
<xs:element name="For">
695689
<xs:complexType mixed="true">
696-
<xs:choice minOccurs="0" maxOccurs="unbounded">
690+
<xs:choice minOccurs="0" maxOccurs="unbounded">
697691
<xs:element ref="IsEmpty" />
698692
<xs:element ref="IsEqual" />
699693
<xs:element ref="IsGreaterEqual" />
@@ -754,7 +748,7 @@
754748
</xs:element>
755749
<xs:element name="Statement">
756750
<xs:complexType mixed="true">
757-
<xs:choice minOccurs="0" maxOccurs="unbounded">
751+
<xs:choice minOccurs="0" maxOccurs="unbounded">
758752
<xs:element ref="IsEmpty" />
759753
<xs:element ref="IsEqual" />
760754
<xs:element ref="IsGreaterEqual" />
@@ -784,11 +778,12 @@
784778
<xs:attribute name="ParameterMap" type="xs:string" use="optional" />
785779
<xs:attribute name="CommandType" type="CommandType" use="optional"/>
786780
<xs:attribute name="SourceChoice" type="DataSourceChoice" use="optional"/>
781+
<xs:attribute name="ReadDb" type="xs:string" use="optional"/>
787782
</xs:complexType>
788783
</xs:element>
789-
<xs:element name="Statements" >
784+
<xs:element name="Statements">
790785
<xs:complexType mixed="true">
791-
<xs:choice minOccurs="1" maxOccurs="unbounded">
786+
<xs:choice minOccurs="1" maxOccurs="unbounded">
792787
<xs:element ref="Statement"/>
793788
</xs:choice>
794789
</xs:complexType>
@@ -797,11 +792,11 @@
797792
<xs:element name="SmartSqlMap">
798793
<xs:complexType mixed="true">
799794
<xs:all>
800-
<xs:element ref="Caches" minOccurs="0" maxOccurs="1"/>
801-
<xs:element ref="ResultMaps" minOccurs="0" maxOccurs="1"/>
802-
<xs:element ref="MultipleResultMaps" minOccurs="0" maxOccurs="1"/>
803-
<xs:element ref="ParameterMaps" minOccurs="0" maxOccurs="1"/>
804-
<xs:element ref="Statements" minOccurs="0" maxOccurs="1"/>
795+
<xs:element ref="Caches" minOccurs="0" maxOccurs="1"/>
796+
<xs:element ref="ResultMaps" minOccurs="0" maxOccurs="1"/>
797+
<xs:element ref="MultipleResultMaps" minOccurs="0" maxOccurs="1"/>
798+
<xs:element ref="ParameterMaps" minOccurs="0" maxOccurs="1"/>
799+
<xs:element ref="Statements" minOccurs="0" maxOccurs="1"/>
805800
</xs:all>
806801
<xs:attribute name="Scope" type="xs:string" use="required" />
807802
</xs:complexType>

src/SmartSql.UTests/Maps/T_Entity.xml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,25 @@
3030
<Result Property="Total"/>
3131
<Result Property="List"/>
3232
</MultipleResultMap>
33+
<MultipleResultMap Id="GetNested_RootMReuslt">
34+
<Root/>
35+
<Result Property="List"/>
36+
</MultipleResultMap>
3337
</MultipleResultMaps>
3438
<Statements>
39+
<Statement Id="Query_ReadDb2" ReadDb="ReadDb-2">
40+
Select Top 10 T.* From T_Entity T
41+
</Statement>
42+
43+
<Statement Id="GetNested_Root" MultipleResultMap="GetNested_RootMReuslt">
44+
Select Count(1) As Total From T_Entity;
45+
Select Top 10 T.* From T_Entity T
46+
</Statement>
3547
<Statement Id="MQueryByPage" MultipleResultMap="QueryByPageMReuslt">
3648
Select Count(1) From T_Entity;
3749
Select Top 10 T.* From T_Entity T
3850
</Statement>
39-
51+
4052
<Statement Id="SP_QueryByPage" CommandType="StoredProcedure">
4153
SP_QueryByPage
4254
</Statement>

src/SmartSql.UTests/SmartSqlMapConfig.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@
55
<!--ParameterPrefix:[SqlServer:@ | MySQL:? |Oracle::] -->
66
<DbProvider Name="SqlClientFactory" ParameterPrefix="@" Type="System.Data.SqlClient.SqlClientFactory,System.Data.SqlClient" />
77
<Write Name="WriteDB" ConnectionString="Data Source=.;Initial Catalog=SmartSqlStarterDB;Integrated Security=True"/>
8+
<Read Name="ReadDb-1" ConnectionString="Data Source=.;Initial Catalog=SmartSqlStarterDB;Integrated Security=True" Weight="100"/>
9+
<Read Name="ReadDb-2" ConnectionString="Data Source=.;Initial Catalog=SmartSqlStarterDB;Integrated Security=True" Weight="1"/>
10+
<Read Name="ReadDb-3" ConnectionString="Data Source=.;Initial Catalog=SmartSqlStarterDB;Integrated Security=True" Weight="100"/>
11+
<Read Name="ReadDb-4" ConnectionString="Data Source=.;Initial Catalog=SmartSqlStarterDB;Integrated Security=True" Weight="100"/>
812
</Database>
9-
13+
1014
<TypeHandlers>
1115
<TypeHandler Name="Json" Type="SmartSql.TypeHandler.JsonTypeHandler,SmartSql.TypeHandler"/>
1216
<TypeHandler Name="Xml" Type="SmartSql.TypeHandler.XmlTypeHandler,SmartSql.TypeHandler"/>
1317
</TypeHandlers>
14-
18+
1519
<SmartSqlMaps>
1620
<SmartSqlMap Path="Maps" Type="Directory"></SmartSqlMap>
1721
</SmartSqlMaps>

src/SmartSql.UTests/SmartSqlMapper_Test.cs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ public SmartSqlMapper_Test()
2020
public void Dispose()
2121
{
2222
_sqlMapper.Dispose();
23-
2423
}
2524
[Fact]
2625
public void BeginSession()
@@ -52,6 +51,27 @@ public void BeginTransaction()
5251
throw ex;
5352
}
5453
}
54+
55+
56+
57+
[Fact]
58+
public void Query_ReadDb2()
59+
{
60+
var result = _sqlMapper.Query<T_Entity>(new RequestContext
61+
{
62+
Scope = Scope,
63+
SqlId = "Query_ReadDb2"
64+
});
65+
}
66+
[Fact]
67+
public void GetNested_Root()
68+
{
69+
var result = _sqlMapper.GetNested<QueryByPageResponse>(new RequestContext
70+
{
71+
Scope = Scope,
72+
SqlId = "GetNested_Root"
73+
});
74+
}
5575
[Fact]
5676
public void GetNested()
5777
{
@@ -468,9 +488,6 @@ await _sqlMapper.ExecuteAsync(new RequestContext
468488
});
469489
}
470490
#endregion
471-
472-
473-
474491
}
475492
public class QueryByPageResponse
476493
{

src/SmartSql/Configuration/Maps/MapFactory.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,15 @@ public static MultipleResultMap LoadMultipleResultMap(XmlElement xmlNode, IList<
166166
var resultMap = resultMaps.FirstOrDefault(m => m.Id == result.MapId);
167167
result.Map = resultMap ?? throw new SmartSqlException($"Can not find ResultMap.Id:{result.MapId}");
168168
}
169-
multipleResultMap.Results.Add(result);
169+
if (childNode.Name == "Root")
170+
{
171+
multipleResultMap.Root = result;
172+
}
173+
else
174+
{
175+
multipleResultMap.Results.Add(result);
176+
}
177+
170178
resultIndex++;
171179
}
172180
return multipleResultMap;

src/SmartSql/Configuration/Maps/MultipleResultMap.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace SmartSql.Configuration.Maps
77
public class MultipleResultMap
88
{
99
public string Id { get; set; }
10+
public Result Root { get; set; }
1011
public List<Result> Results { get; set; }
1112
}
1213
public class Result

src/SmartSql/Configuration/StatementFactory.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ public Statement Load(XmlElement statementNode, SmartSqlMap smartSqlMap)
2323
{
2424
Id = statementNode.Attributes["Id"].Value,
2525
SqlTags = new List<ITag> { },
26+
ReadDb = statementNode.Attributes["ReadDb"]?.Value,
2627
SmartSqlMap = smartSqlMap
2728
};
29+
2830
var cmdTypeStr = statementNode.Attributes["CommandType"]?.Value;
2931
var sourceChoiceStr = statementNode.Attributes["SourceChoice"]?.Value;
3032
if (Enum.TryParse<CommandType>(cmdTypeStr, out CommandType cmdType))

src/SmartSql/Configuration/Statements/Statement.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public class Statement
3131
public CommandType? CommandType { get; set; }
3232
[XmlAttribute]
3333
public DataSourceChoice? SourceChoice { get; set; }
34+
[XmlAttribute]
35+
public String ReadDb { get; set; }
3436
public String FullSqlId => $"{SmartSqlMap.Scope}.{Id}";
3537
public IList<ITag> SqlTags { get; set; }
3638
public Cache Cache { get; set; }

src/SmartSql/DataReaderDeserializer/NestedObjectConvertFactory.cs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
using System.Data;
99
using System.Reflection;
1010
using System.Reflection.Emit;
11-
using System.Text;
12-
using System.Threading.Tasks;
1311

1412
namespace SmartSql.DataReaderDeserializer
1513
{
@@ -47,11 +45,26 @@ private Func<RequestContext, IDataReaderWrapper, IDataReaderDeserializer, object
4745
var dynamicMethod = new DynamicMethod("NestedObjectConvert_" + Guid.NewGuid().ToString("N"), targetType, new[] { TypeUtils.RequestContextType, _dataReaderWrapperType, _deserType }, targetType, true);
4846
var iLGenerator = dynamicMethod.GetILGenerator();
4947
iLGenerator.DeclareLocal(targetType);
50-
ConstructorInfo targetCtor = targetType.GetConstructor(
51-
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
52-
iLGenerator.Emit(OpCodes.Newobj, targetCtor); // [target]
53-
iLGenerator.Emit(OpCodes.Stloc_0);
5448
MultipleResultMap multipleResultMap = requestContext.Statement.MultipleResultMap;
49+
if (multipleResultMap.Root != null)
50+
{
51+
iLGenerator.Emit(OpCodes.Ldarg_2);
52+
iLGenerator.Emit(OpCodes.Ldarg_0);
53+
iLGenerator.Emit(OpCodes.Ldarg_1);
54+
iLGenerator.Emit(OpCodes.Ldc_I4_0);
55+
var deserToRoot = _deserToSingle.MakeGenericMethod(targetType);
56+
iLGenerator.Emit(OpCodes.Call, deserToRoot);
57+
iLGenerator.Emit(OpCodes.Stloc_0);
58+
EmitNextResult(iLGenerator);
59+
}
60+
else
61+
{
62+
ConstructorInfo targetCtor = targetType.GetConstructor(
63+
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
64+
iLGenerator.Emit(OpCodes.Newobj, targetCtor); // [target]
65+
iLGenerator.Emit(OpCodes.Stloc_0);
66+
}
67+
5568
foreach (var result in multipleResultMap.Results)
5669
{
5770
var property = targetType.GetProperty(result.Property);
@@ -74,16 +87,19 @@ private Func<RequestContext, IDataReaderWrapper, IDataReaderDeserializer, object
7487
iLGenerator.Emit(OpCodes.Ldc_I4_0);
7588
iLGenerator.Emit(OpCodes.Call, executeMethod);
7689
iLGenerator.Emit(OpCodes.Call, property.SetMethod);
77-
iLGenerator.Emit(OpCodes.Ldarg_1);
78-
iLGenerator.Emit(OpCodes.Call, _dataReader_NextResult);
79-
iLGenerator.Emit(OpCodes.Pop);
90+
EmitNextResult(iLGenerator);
8091
}
8192
iLGenerator.Emit(OpCodes.Ldloc_0);
8293
iLGenerator.Emit(OpCodes.Ret);
8394
var funcType = System.Linq.Expressions.Expression.GetFuncType(TypeUtils.RequestContextType, _dataReaderWrapperType, _deserType, targetType);
8495
return (Func<RequestContext, IDataReaderWrapper, IDataReaderDeserializer, object>)dynamicMethod.CreateDelegate(funcType);
8596
}
8697

87-
98+
private void EmitNextResult(ILGenerator iLGenerator)
99+
{
100+
iLGenerator.Emit(OpCodes.Ldarg_1);
101+
iLGenerator.Emit(OpCodes.Call, _dataReader_NextResult);
102+
iLGenerator.Emit(OpCodes.Pop);
103+
}
88104
}
89105
}

src/SmartSql/DataSourceFilter.cs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using SmartSql.Abstractions;
33
using SmartSql.Abstractions.DataSource;
44
using SmartSql.Abstractions.DbSession;
5+
using SmartSql.Exceptions;
56
using SmartSql.Utils;
67
using System;
78
using System.Collections.Generic;
@@ -34,24 +35,37 @@ public IDataSource Elect(RequestContext context)
3435
{
3536
return _dbSessionStore.LocalSession.DataSource;
3637
}
37-
return GetDataSource(context.DataSourceChoice);
38+
return GetDataSource(context);
3839
}
3940

40-
private IDataSource GetDataSource(DataSourceChoice sourceChoice)
41+
private IDataSource GetDataSource(RequestContext context)
4142
{
43+
var sourceChoice = context.DataSourceChoice;
4244
IDataSource choiceDataSource = _smartSqlContext.Database.WriteDataSource;
4345
var readDataSources = _smartSqlContext.Database.ReadDataSources;
4446
if (sourceChoice == DataSourceChoice.Read
4547
&& readDataSources != null
4648
&& readDataSources.Count > 0
4749
)
4850
{
49-
var seekList = readDataSources.Select(readDataSource => new WeightFilter<IReadDataSource>.WeightSource
51+
var statement = context.Statement;
52+
if (statement != null && !String.IsNullOrEmpty(statement.ReadDb))
5053
{
51-
Source = readDataSource,
52-
Weight = readDataSource.Weight
53-
});
54-
choiceDataSource = _weightFilter.Elect(seekList).Source;
54+
choiceDataSource = readDataSources.FirstOrDefault(readDb => readDb.Name == statement.ReadDb);
55+
if (choiceDataSource == null)
56+
{
57+
throw new SmartSqlException($"Statement.Id:{statement.FullSqlId},can not find ReadDb:{statement.ReadDb} .");
58+
}
59+
}
60+
else
61+
{
62+
var seekList = readDataSources.Select(readDataSource => new WeightFilter<IReadDataSource>.WeightSource
63+
{
64+
Source = readDataSource,
65+
Weight = readDataSource.Weight
66+
});
67+
choiceDataSource = _weightFilter.Elect(seekList).Source;
68+
}
5569
}
5670
if (_logger.IsEnabled(LogLevel.Debug))
5771
{

0 commit comments

Comments
 (0)