Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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