Skip to content
14 changes: 14 additions & 0 deletions src/SmartSql.Test.Unit/ConfigBuilder/XmlConfigLoaderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Text;
using SmartSql.ConfigBuilder;
using SmartSql.Exceptions;
using Xunit;

namespace SmartSql.Test.Unit.ConfigBuilder
Expand All @@ -14,5 +15,18 @@ public void Load()
var configLoader = new XmlConfigBuilder(ResourceType.File, "SmartSqlMapConfig.xml");
var config = configLoader.Build();
}
[Fact]
public void LoadFailTest()
{
try
{
var configLoader = new XmlConfigBuilder(ResourceType.File, "SmartSqlMapConfig2.xml");
var config = configLoader.Build();
}
catch (SmartSqlException ex)
{
Assert.StartsWith( "Read Nodes must have Weight attribute",ex.Message);
}
}
}
}
3 changes: 3 additions & 0 deletions src/SmartSql.Test.Unit/SmartSql.Test.Unit.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@
<None Update="Maps\T_Entity.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="SmartSqlMapConfig2.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="SmartSqlMapConfig.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
Expand Down
2 changes: 1 addition & 1 deletion src/SmartSql.Test.Unit/SmartSqlMapConfig.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
<DbProvider Name="${DbProvider}"/>
<Write Name="WriteDB" ConnectionString="${ConnectionString}"/>
<Read Name="ReadDb-1" ConnectionString="${ConnectionString}" Weight="100"/>
<Read Name="ReadDb-2" ConnectionString="${ConnectionString}" Weight="100"/>
<Read Name="ReadDb-2" ConnectionString="${ConnectionString}" Weight="100" />
</Database>
<TypeHandlers>
<TypeHandler PropertyType="SmartSql.Test.Entities.UserInfo,SmartSql.Test" Type="${JsonTypeHandler`}">
Expand Down
99 changes: 99 additions & 0 deletions src/SmartSql.Test.Unit/SmartSqlMapConfig2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8" ?>
<SmartSqlMapConfig xmlns="http://SmartSql.net/schemas/SmartSqlMapConfig.xsd">
<Settings IgnoreParameterCase="false" ParameterPrefix="$" IsCacheEnabled="true" EnablePropertyChangedTrack="true"
IgnoreDbNull="true"/>
<Properties>
<!-- <Property Name="Redis" Value="localhost"/>-->
<Property Name="DbProvider" Value="MsSqlServer"/>
<Property Name="ConnectionString"
Value="Data Source=.;Initial Catalog=SmartSqlTestDB;Integrated Security=True"/>
<Property Name="JsonTypeHandler`" Value="SmartSql.TypeHandler.JsonTypeHandler`1,SmartSql.TypeHandler"/>
<Property Name="JsonTypeHandler" Value="SmartSql.TypeHandler.JsonTypeHandler,SmartSql.TypeHandler"/>
<Property Name="ScriptBuilder" Value="SmartSql.ScriptTag.ScriptBuilder,SmartSql.ScriptTag"/>
<Property Name="RedisCacheProvider" Value="SmartSql.Cache.Redis.RedisCacheProvider,SmartSql.Cache.Redis"/>
</Properties>
<AutoConverters>
<AutoConverter Name="NoneConverter">
<Tokenizer Name="None"/>
<Converter Name="None"/>
</AutoConverter>
<AutoConverter Name="Default" Default="true">
<Tokenizer Name="Default"/>
<Converter Name="Pascal"/>
</AutoConverter>
<AutoConverter Name="PascalConverter">
<Tokenizer Name="Default">
<Properties>
<Property Name="IgnorePrefix" Value=""/>
<Property Name="Delimiter" Value="_"/>
<Property Name="UppercaseSplit" Value="false"/>
</Properties>
</Tokenizer>
<Converter Name="Pascal"/>
</AutoConverter>
<AutoConverter Name="DelimiterConverter">
<Tokenizer Name="Default">
<Properties>
<Property Name="IgnorePrefix" Value="col_"/>
<Property Name="Delimiter" Value="_"/>
<Property Name="UppercaseSplit" Value="true"/>
</Properties>
</Tokenizer>
<Converter Name="Delimiter">
<Properties>
<Property Name="Prefix" Value="Col_"/>
<Property Name="Delimiter" Value="_"/>
<Property Name="Mode" Value="FirstUpper"/>
</Properties>
</Converter>
</AutoConverter>
</AutoConverters>
<Database>
<!-- MsSqlServer: Microsoft.Data.SqlClient , SqlServer: System.Data.SqlClinet -->
<DbProvider Name="${DbProvider}"/>
<Write Name="WriteDB" ConnectionString="${ConnectionString}"/>
<Read Name="ReadDb-1" ConnectionString="${ConnectionString}" Weight="100"/>
<Read Name="ReadDb-2" ConnectionString="${ConnectionString}" />
</Database>
<TypeHandlers>
<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>
<TypeHandler Name="AnsiStringTypeHandler" Type="SmartSql.TypeHandlers.StringTypeHandler,SmartSql">
<Properties>
<Property Name="DbType" Value="AnsiString"/>
</Properties>
</TypeHandler>
<TypeHandler Name="AnsiStringFixedLengthTypeHandler" Type="SmartSql.TypeHandlers.StringTypeHandler,SmartSql">
<Properties>
<Property Name="DbType" Value="AnsiStringFixedLength"/>
</Properties>
</TypeHandler>
<TypeHandler Name="Json" Type="${JsonTypeHandler}"></TypeHandler>

</TypeHandlers>
<TagBuilders>
<TagBuilder Name="Script" Type="${ScriptBuilder}"/>
</TagBuilders>
<IdGenerators>
<IdGenerator Name="SnowflakeId" Type="SnowflakeId">
<Properties>
<Property Name="WorkerIdBits" Value="9"/>
<Property Name="WorkerId" Value="511"/>
<Property Name="Sequence" Value="14"/>
</Properties>
</IdGenerator>
<IdGenerator Name="DbSequence" Type="DbSequence">
<Properties>
<Property Name="Step" Value="10"/>
<Property Name="SequenceSql" Value="Select Next Value For IdSequence;"/>
</Properties>
</IdGenerator>
</IdGenerators>
<SmartSqlMaps>
<SmartSqlMap Path="Maps" Type="Directory"></SmartSqlMap>
</SmartSqlMaps>
</SmartSqlMapConfig>
78 changes: 43 additions & 35 deletions src/SmartSql/ConfigBuilder/XmlConfigBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class XmlConfigBuilder : AbstractConfigBuilder

private readonly IWordsConverterBuilder _wordsConverterBuilder = new WordsConverterBuilder();
private readonly ITokenizerBuilder _tokenizerBuilder = new TokenizerBuilder();

public XmlConfigBuilder(ResourceType resourceType, string resourcePath, ILoggerFactory loggerFactory = null)
{
_resourceType = resourceType;
Expand Down Expand Up @@ -153,12 +153,8 @@ protected override void BuildDatabase()
database.Write.DbProvider = database.DbProvider;
var readDataSourceNodes = databaseNode.SelectNodes($"{CONFIG_PREFIX}:Read", XmlNsManager);
if (readDataSourceNodes == null) return;
foreach (XmlNode readNode in readDataSourceNodes)
{
var readDb = ParseReadDataSource(readNode);
readDb.DbProvider = database.DbProvider;
database.Reads.Add(readDb.Name, readDb);
}
var readDataSources = this.ParseReadDataSource(readDataSourceNodes, database.DbProvider);
database.Reads.AddRange(readDataSources);
}

private DbProvider ParseDbProvider(XmlNode dbProviderNode)
Expand Down Expand Up @@ -226,34 +222,46 @@ private WriteDataSource ParseWriteDataSource(XmlNode writeDataSourceNode)
{
writeDataSource.ConnectionString = connectionString;
}

return writeDataSource;
}
private ReadDataSource ParseReadDataSource(XmlNode readDataSourceNode)
private IDictionary<string, ReadDataSource> ParseReadDataSource(XmlNodeList readDataSourceNodes, DbProvider dbProvider)
{
if (readDataSourceNode == null)
{
throw new SmartSqlException("ReadDataSource can not be null.");
}
var readDataSource = new ReadDataSource();
if (readDataSourceNode.Attributes.TryGetValueAsString(nameof(ReadDataSource.Name), out string name, SmartSqlConfig.Properties)
)
{
readDataSource.Name = name;
}
if (readDataSourceNode.Attributes.TryGetValueAsString(nameof(ReadDataSource.ConnectionString), out string connectionString, SmartSqlConfig.Properties)
)
{
readDataSource.ConnectionString = connectionString;
}
if (readDataSourceNode.Attributes.TryGetValueAsInt32(nameof(ReadDataSource.Weight), out int weight, SmartSqlConfig.Properties)
)
{
readDataSource.Weight = weight;
var readDataSources = new Dictionary<string, ReadDataSource>();
var s = new List<string>();
foreach (XmlNode readDataSourceNode in readDataSourceNodes)
{

var readDataSource = new ReadDataSource();
if (readDataSourceNode.Attributes.TryGetValueAsString(nameof(ReadDataSource.Name), out string name, SmartSqlConfig.Properties) )
{
readDataSource.Name = name;
}
else
{
throw new SmartSqlException($"Read Nodes must have Name attribute");
}
if (readDataSourceNode.Attributes.TryGetValueAsString(nameof(ReadDataSource.ConnectionString), out string connectionString, SmartSqlConfig.Properties) )
{
readDataSource.ConnectionString = connectionString;
}
if (readDataSourceNode.Attributes.TryGetValueAsInt32(nameof(ReadDataSource.Weight), out int weight, SmartSqlConfig.Properties) )
{
readDataSource.Weight = weight;
}
else
{
if (readDataSourceNodes.Count > 1)
{
throw new SmartSqlException($"Read Nodes must have Weight attribute,Name is {readDataSource.Name}");
}
}
readDataSource.DbProvider = dbProvider;
readDataSources.Add(readDataSource.Name, readDataSource);
}

return readDataSource;
return readDataSources;
}

#endregion
#region 3. TypeHandlers
protected override void BuildTypeHandlers()
Expand Down Expand Up @@ -414,7 +422,7 @@ private void BuildAutoConverter(XmlNode autoConverterNode)
var wordsConverter = BuildWordsConverter(wordsConverterNode);

var autoConverter = new AutoConverter.AutoConverter(converterName, tokenizer, wordsConverter);

SmartSqlConfig.AutoConverters.Add(autoConverter.Name, autoConverter);
if (isDefault)
{
Expand All @@ -431,7 +439,7 @@ private ITokenizer BuildTokenizer(XmlNode tokenizerNode)
var properties = ParseProperties(tokenizerNode);
return _tokenizerBuilder.Build(tokenizerName, properties);
}

private IWordsConverter BuildWordsConverter(XmlNode wordsConverterNode)
{
if (!wordsConverterNode.Attributes.TryGetValueAsString("Name", out String wordsConverterName, SmartSqlConfig.Properties))
Expand All @@ -441,10 +449,10 @@ private IWordsConverter BuildWordsConverter(XmlNode wordsConverterNode)
var properties = ParseProperties(wordsConverterNode);
return _wordsConverterBuilder.Build(wordsConverterName, properties);
}

#endregion


private IDictionary<String, object> ParseProperties(XmlNode parentNode)
{
var parametersNode = parentNode.SelectSingleNode($"{CONFIG_PREFIX}:Properties", XmlNsManager);
Expand Down
7 changes: 7 additions & 0 deletions src/SmartSql/Utils/DictionaryExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ public static void EnsureValue<TKey, TValue, TTypedValue>(this IDictionary<TKey,
throw new SmartSqlException($"Can not find Parameter:{key}!");
}
}
public static void AddRange<TKey, TValue>(this IDictionary<TKey,TValue> dic, IDictionary<TKey,TValue> collection)
{
foreach(var item in collection)
{
dic.Add(item);
}
}

}
}
12 changes: 11 additions & 1 deletion src/SmartSql/Utils/WeightFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace SmartSql.Utils
/// </summary>
public class WeightFilter<T>
{

/// <summary>
/// 选举权重源
/// </summary>
Expand All @@ -20,7 +21,16 @@ public WeightSource Elect(IEnumerable<WeightSource> inWeightSources)
{
var random = new Random((int)Stopwatch.GetTimestamp());
var weightSources = inWeightSources.ToList();
int totalWeight = weightSources.Sum(source => source.Weight);
int totalWeight = 0;
if (weightSources.Count ==1)
{
return weightSources[0];
}
else
{
totalWeight=weightSources.Sum(source => source.Weight);
}

int position = random.Next(1, totalWeight);
return FindByPosition(weightSources, position);
}
Expand Down