-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathDataSourceSelector.cs
More file actions
122 lines (105 loc) · 3.99 KB
/
DataSourceSelector.cs
File metadata and controls
122 lines (105 loc) · 3.99 KB
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
37
38
39
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
* _____ ______
* /_ / ____ ____ ____ _________ / __/ /_
* / / / __ \/ __ \/ __ \/ ___/ __ \/ /_/ __/
* / /__/ /_/ / / / / /_/ /\_ \/ /_/ / __/ /_
* /____/\____/_/ /_/\__ /____/\____/_/ \__/
* /____/
*
* Authors:
* 钟峰(Popeye Zhong) <zongsoft@qq.com>
*
* Copyright (C) 2010-2020 Zongsoft Studio <http://www.zongsoft.com>
*
* This file is part of Zongsoft.Data library.
*
* The Zongsoft.Data is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3.0 of the License,
* or (at your option) any later version.
*
* The Zongsoft.Data is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Zongsoft.Data library. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Linq;
using System.Collections.Generic;
namespace Zongsoft.Data.Common;
public class DataSourceSelector : IDataSourceSelector
{
#region 成员字段
private readonly string _defaultDriver;
private readonly Dictionary<string, DataSourceWeighter> _weighters;
#endregion
#region 私有构造
public DataSourceSelector(IEnumerable<IDataSource> sources)
{
if(sources == null)
throw new ArgumentNullException(nameof(sources));
foreach(var source in sources)
{
if(string.IsNullOrEmpty(_defaultDriver))
_defaultDriver = source.Driver.Name;
if(!source.Name.Contains(DataSource.SEPARATOR))
{
_defaultDriver = source.Driver.Name;
break;
}
}
_weighters = new Dictionary<string, DataSourceWeighter>(StringComparer.OrdinalIgnoreCase);
foreach(var group in sources.GroupBy(source => source.Driver.Name, StringComparer.OrdinalIgnoreCase))
_weighters[group.Key] = new DataSourceWeighter(group);
}
#endregion
#region 公共方法
public IDataSource GetSource(IDataAccessContextBase context)
{
var driver = this.GetDriver(context);
if(driver != null && _weighters.TryGetValue(driver, out var weighter))
return weighter.Get(context);
return null;
}
#endregion
#region 私有方法
private string GetDriver(IDataAccessContextBase context)
{
if(context is DataExecuteContextBase exectution && exectution.Command != null)
{
foreach(var driver in exectution.Command.Scriptor.Drivers)
{
if(_weighters.ContainsKey(driver))
return driver;
}
}
return string.IsNullOrEmpty(context.Driver) ? _defaultDriver : context.Driver;
}
#endregion
#region 加权计重
private class DataSourceWeighter
{
private readonly Components.Weighter<IDataSource> _readables;
private readonly Components.Weighter<IDataSource> _writables;
public DataSourceWeighter(IEnumerable<IDataSource> sources)
{
_readables = new Components.Weighter<IDataSource>(sources.Where(source => (source.Mode & DataAccessMode.ReadOnly) == DataAccessMode.ReadOnly), source => GetWeight(source));
_writables = new Components.Weighter<IDataSource>(sources.Where(source => (source.Mode & DataAccessMode.WriteOnly) == DataAccessMode.WriteOnly), source => GetWeight(source));
}
public IDataSource Get(IDataAccessContextBase context)
{
return context.Method switch
{
DataAccessMethod.Select or DataAccessMethod.Exists or DataAccessMethod.Aggregate => _readables.Get(),
DataAccessMethod.Execute => ((DataExecuteContextBase)context).Command.Mutability == Metadata.DataCommandMutability.None ? _readables.Get() : _writables.Get(),
_ => _writables.Get(),
};
}
private static int GetWeight(IDataSource source, int defaultValue = 100) =>
source.Properties.TryGetValue("weight", out var value) && Zongsoft.Common.Convert.TryConvertValue<int>(value, out var weight) ? Math.Max(weight, 0) : defaultValue;
}
#endregion
}