프로젝트

일반

사용자정보

개정판 d952e1d5

IDd952e1d59383dcc2a044df79a1ae015ae2c7a7c7
상위 0fce3dac
하위 ffaddd56

김태성이(가) 약 2년 전에 추가함

issue #0000 dapper MixParameters 추가

Change-Id: Id173a927d1285da194e948cac8100232a556a983

차이점 보기:

ConvertService/ServiceBase/Markus.Service.DataBase.Dapper/MixParameters.cs
1
using Dapper;
2
using Npgsql;
3
using NpgsqlTypes;
4
using System;
5
using System.Collections.Generic;
6
using System.Data;
7
using System.Linq;
8

  
9
namespace Markus.Service.DataBase
10
{
11
    internal class MixParameters : SqlMapper.IDynamicParameters, SqlMapper.IParameterLookup
12
    {
13
        public MixParameters(DBMSType dbms)
14
        {
15
            DBMS = dbms;
16
        }
17

  
18
        private DBMSType DBMS = DBMSType.MSSQL;
19

  
20
        internal const DbType EnumerableMultiParameter = (DbType)(-1);
21
        private static readonly Dictionary<SqlMapper.Identity, Action<IDbCommand, object>> paramReaderCache = new Dictionary<SqlMapper.Identity, Action<IDbCommand, object>>();
22
        private readonly Dictionary<string, ParamInfo> _parameters = new Dictionary<string, ParamInfo>();
23
        private List<object> templates;
24

  
25
        /// <summary>
26
        ///     All the names of the param in the bag, use Get to yank them out
27
        /// </summary>
28
        public IEnumerable<string> ParameterNames
29
        {
30
            get { return _parameters.Select(p => p.Key); }
31
        }
32

  
33
        public int ParameterCount
34
        {
35
            get { return _parameters.Count; }
36
        }
37

  
38
        object SqlMapper.IParameterLookup.this[string name] =>
39
             _parameters.TryGetValue(name, out ParamInfo param) ? param.Value : null;
40

  
41
        internal static bool ShouldSetDbType(DbType? dbType)
42
            => dbType.HasValue && dbType.GetValueOrDefault() != EnumerableMultiParameter;
43

  
44
        internal static bool ShouldSetDbType(DbType dbType)
45
            => dbType != EnumerableMultiParameter; // just in case called with non-nullable
46

  
47
        void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command, SqlMapper.Identity identity)
48
        {
49
            if (templates != null)
50
                foreach (var template in templates)
51
                {
52
                    var newIdent = identity.ForDynamicParameters(template.GetType());
53
                    Action<IDbCommand, object> appender;
54

  
55
                    lock (paramReaderCache)
56
                    {
57
                        if (!paramReaderCache.TryGetValue(newIdent, out appender))
58
                        {
59
                            appender = SqlMapper.CreateParamInfoGenerator(newIdent, false, true);
60
                            paramReaderCache[newIdent] = appender;
61
                        }
62
                    }
63

  
64
                    appender(command, template);
65
                }
66

  
67
            switch (DBMS)
68
            {
69
                case DBMSType.POSTGRESQL:
70
                case DBMSType.MSSQL:
71
                    msSqlAddParamaters(command, identity);
72
                    break;
73
                //case DBMSType.POSTGRESQL:
74
                //    npgAddParamaters(command, identity);
75
                    //break;
76
                default:
77
                    break;
78
            }
79
        }
80

  
81
        private void msSqlAddParamaters(IDbCommand command, SqlMapper.Identity identity)
82
        {
83
            foreach (var param in _parameters.Values)
84
            {
85
                if (param.CameFromTemplate) continue;
86

  
87
                var dbType = param.DbType;
88
                var val = param.Value;
89
                string name = Clean(param.Name);
90
                var isCustomQueryParameter = val is SqlMapper.ICustomQueryParameter;
91

  
92
                SqlMapper.ITypeHandler handler = null;
93
                if (dbType == null && val != null && !isCustomQueryParameter)
94
                {
95
#pragma warning disable 618
96
                    dbType = SqlMapper.LookupDbType(val.GetType(), name, true, out handler);
97
#pragma warning disable 618
98
                }
99
                if (isCustomQueryParameter)
100
                {
101
                    ((SqlMapper.ICustomQueryParameter)val).AddParameter(command, name);
102
                }
103
                else if (dbType == EnumerableMultiParameter)
104
                {
105
#pragma warning disable 612, 618
106
                    SqlMapper.PackListParameters(command, name, val);
107
#pragma warning restore 612, 618
108
                }
109
                else
110
                {
111
                    bool add = !command.Parameters.Contains(name);
112
                    IDbDataParameter p;
113
                    if (add)
114
                    {
115
                        p = command.CreateParameter();
116
                        p.ParameterName = name;
117
                    }
118
                    else
119
                    {
120
                        p = (IDbDataParameter)command.Parameters[name];
121
                    }
122

  
123
                    p.Direction = param.ParameterDirection;
124
                    if (handler == null)
125
                    {
126
#pragma warning disable 0618
127
                        p.Value = SqlMapper.SanitizeParameterValue(val);
128
#pragma warning restore 0618
129
                        if (ShouldSetDbType(dbType) && p.DbType != dbType.GetValueOrDefault())
130
                        {
131
                            p.DbType = dbType.GetValueOrDefault();
132
                        }
133
                        var s = val as string;
134
                        if (s?.Length <= DbString.DefaultLength)
135
                        {
136
                            p.Size = DbString.DefaultLength;
137
                        }
138
                        if (param.Size != null) p.Size = param.Size.Value;
139
                        if (param.Precision != null) p.Precision = param.Precision.Value;
140
                        if (param.Scale != null) p.Scale = param.Scale.Value;
141
                    }
142
                    else
143
                    {
144
                        if (ShouldSetDbType(dbType)) p.DbType = dbType.GetValueOrDefault();
145
                        if (param.Size != null) p.Size = param.Size.Value;
146
                        if (param.Precision != null) p.Precision = param.Precision.Value;
147
                        if (param.Scale != null) p.Scale = param.Scale.Value;
148
                        handler.SetValue(p, val ?? DBNull.Value);
149
                    }
150

  
151
                    if (add)
152
                    {
153
                        command.Parameters.Add(p);
154
                    }
155
                    param.AttachedParam = p;
156
                }
157
            }
158

  
159
            // note: most non-privileged implementations would use: this.ReplaceLiterals(command);
160
            //if (literals.Count != 0) SqlMapper.ReplaceLiterals(this, command);
161
        }
162

  
163
        private void npgAddParamaters(IDbCommand command, SqlMapper.Identity identity)
164
        { 
165
            foreach (var param in _parameters.Values)
166
            {
167
                if (((NpgsqlCommand)command).Parameters.Contains(param.Name))
168
                {
169
                    ((NpgsqlCommand)command).Parameters.Remove(param.Name);
170
                }
171

  
172
                var p = ParamInfoToNpgParam(param);
173
                p.ParameterName = param.Name;
174

  
175
                command.Parameters.Add(p);
176

  
177
                param.AttachedParam = p;
178
            }
179
        }
180

  
181
        private NpgsqlParameter ParamInfoToNpgParam(ParamInfo param)
182
        {
183
            NpgsqlParameter p = new NpgsqlParameter();
184

  
185
            var val = param.Value;
186
            p.Value = val ?? DBNull.Value;
187
            p.Direction = param.ParameterDirection;
188
            if (param.Size != null) p.Size = param.Size.Value;
189
            if (param.NpgsqlType != null)
190
            {
191
                p.NpgsqlDbType = param.NpgsqlType.Value;
192
            }
193
            else if (param.Value != null)
194
            {
195
                var npgType = dbTypeConvert.GetNpgsqlDbType(param.Value.GetType()).Value;
196

  
197
                if (npgType == NpgsqlDbType.Text)
198
                {
199
                    //npgType = NpgsqlDbType.Varchar;
200
                }
201

  
202
                p.NpgsqlDbType = npgType;
203
            }
204
            else if (param.DbType != null)
205
            {
206
                var npgType = dbTypeConvert.GetNpgsqlDbType(param.DbType.Value).Value;
207

  
208
                if (npgType == NpgsqlDbType.Text)
209
                {
210
                    //npgType = NpgsqlDbType.Varchar;
211
                }
212

  
213
                p.NpgsqlDbType = npgType;
214
            }
215
            else
216
            {
217
                throw new Exception($"{param.Name} npgSQL type을 알 수 없습니다.");
218
            }
219

  
220
            return p;
221
        }
222

  
223
        private static string Clean(string name)
224
        {
225
            if (!string.IsNullOrEmpty(name))
226
            {
227
                switch (name[0])
228
                {
229
                    case '@':
230
                    case ':':
231
                    case '?':
232
                        return name.Substring(1);
233
                }
234
            }
235
            return name;
236
        }
237
        internal void Add(string name,object value = null,NpgsqlTypes.NpgsqlDbType? npgsqlDbType = null, DbType? dbType = null, ParameterDirection? direction = null, int? size = null)
238
        {
239
            if(DBMS == DBMSType.MSSQL)
240
            {
241
                switch (direction)
242
                {
243
                    case ParameterDirection.Output:
244
                    case ParameterDirection.InputOutput:
245
                        if(size == null)
246
                        {
247
                            size = 50;
248
                            //throw new Exception($"{name}는 MSSQL인 경우 direction이 {direction.ToString()}이므로 size를 지정하여야 합니다.");
249
                        }
250
                    break;
251
                    default:
252
                        break;
253
                }
254
            }
255

  
256
            _parameters[Clean(name)] = new ParamInfo
257
            {
258
                Name = name,
259
                Value = value,
260
                ParameterDirection = direction ?? ParameterDirection.Input,
261
                DbType = dbType,
262
                NpgsqlType = npgsqlDbType,
263
                Size = size
264
            };
265
        }
266

  
267
        internal T Get<T>(string name)
268
        {
269
            var val = _parameters[name].AttachedParam.Value;
270
            if (val == DBNull.Value)
271
            {
272
                if (default(T) != null)
273
                    throw new ApplicationException("Attempting to cast a DBNull to a non nullable type!");
274
                return default(T);
275
            }
276

  
277
            return (T)val;
278
        }
279

  
280

  
281
        public NpgsqlParameter Get(string name)
282
        {
283
            return ParamInfoToNpgParam(_parameters[name]);
284
        }
285

  
286
        private class ParamInfo
287
        {
288
            public string Name { get; set; }
289
            public object Value { get; set; }
290
            public ParameterDirection ParameterDirection { get; set; }
291
            public DbType? DbType { get; set; }
292

  
293
            public NpgsqlTypes.NpgsqlDbType? NpgsqlType { get; set; }
294
            public int? Size { get; set; }
295
            public IDbDataParameter AttachedParam { get; set; }
296
            internal Action<object, DynamicParameters> OutputCallback { get; set; }
297
            internal object OutputTarget { get; set; }
298
            internal bool CameFromTemplate { get; set; }
299

  
300
            public byte? Precision { get; set; }
301
            public byte? Scale { get; set; }
302
        }
303
    }
304
}
ConvertService/ServiceBase/Markus.Service.DataBase.Dapper/QueryParameters.cs
1
using Dapper;
2
using System;
3
using System.Collections;
4
using System.Collections.Generic;
5
using System.Data;
6
using System.Linq;
7
using System.Text;
8
using System.Threading.Tasks;
9
using System.Linq.Expressions;
10
using System.Reflection;
11
using System.Reflection.Emit;
12
using System.ComponentModel;
13
using System.Data.SqlTypes;
14
using System.Dynamic;
15
using System.Globalization;
16
using System.Text.RegularExpressions;
17
using System.Diagnostics;
18

  
19
namespace Markus.Service.DataBase
20
{
21
    public partial class QueryParameters : SqlMapper.IDynamicParameters
22
    {
23
        DBMSType DBMS;
24

  
25
        public QueryParameters(DBMSType dbms)
26
        {
27
            DBMS = dbms;
28
        }
29

  
30
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
31
        ////////////////////////////////////////////////////////////////////////////////////////// Private
32

  
33
        #region Field
34

  
35
        /// <summary>
36
        /// 동적 매개 변수 목록
37
        /// </summary>
38
        private readonly DynamicParameters dynamicParameters = new DynamicParameters();
39

  
40
        /// <summary>
41
        /// 오라클 매개 변수 리스트
42
        /// </summary>
43
        private readonly List<Npgsql.NpgsqlParameter> NpgsqlParameterList = new List<Npgsql.NpgsqlParameter>();
44

  
45
        #endregion
46

  
47
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
48
        ////////////////////////////////////////////////////////////////////////////////////////// Public
49

  
50
        #region 추가하기 - Add(name, value, dbType, direction, size)
51

  
52
        /// <summary>
53
        /// 추가하기
54
        /// </summary>
55
        /// <param name="name">명칭</param>
56
        /// <param name="value">값</param>
57
        /// <param name="dbType">DB 타입</param>
58
        /// <param name="direction">방향</param>
59
        /// <param name="size">크기</param>
60
        public void Add(string name, object value = null, DbType? dbType = null, ParameterDirection? direction = null, int? size = null)
61
        {
62
            if (DBMS == DBMSType.MSSQL)
63
            {
64
                this.dynamicParameters.Add(name, value, dbType, direction, size);
65
            }
66
            else
67
            {
68
                Npgsql.NpgsqlParameter parameter = new Npgsql.NpgsqlParameter(parameterName: name, parameterType: dbType)
69
                {
70
                    Direction = direction.GetValueOrDefault()
71
                };
72

  
73
                this.NpgsqlParameterList.Add(parameter);
74
            }
75
        }
76

  
77
        #endregion
78
        #region 추가하기 - Add(name, oracleDbType, direction)
79

  
80
        /// <summary>
81
        /// 추가하기
82
        /// </summary>
83
        /// <param name="name">명칭</param>
84
        /// <param name="oracleDbType">오라클 DB 타입</param>
85
        /// <param name="direction">방향</param>
86
        public void Add(string name, NpgsqlTypes.NpgsqlDbType dbType, ParameterDirection direction)
87
        {
88
            Npgsql.NpgsqlParameter parameter = new Npgsql.NpgsqlParameter(parameterName: name, parameterType: dbType)
89
            {
90
                Direction = direction
91
            };
92

  
93
            this.NpgsqlParameterList.Add(parameter);
94
        }
95

  
96
        #endregion
97
    }
98
}
ConvertService/ServiceBase/Markus.Service.DataBase.Dapper/Repositories/QueryParameters.cs
1
using Dapper;
2
using System;
3
using System.Collections;
4
using System.Collections.Generic;
5
using System.Data;
6
using System.Linq;
7
using System.Text;
8
using System.Threading.Tasks;
9
using System.Linq.Expressions;
10
using System.Reflection;
11
using System.Reflection.Emit;
12
using System.ComponentModel;
13
using System.Data.SqlTypes;
14
using System.Dynamic;
15
using System.Globalization;
16
using System.Text.RegularExpressions;
17
using System.Diagnostics;
18

  
19
namespace Markus.Service.DataBase
20
{
21
    public partial class QueryParameters : SqlMapper.IDynamicParameters, SqlMapper.IParameterLookup, SqlMapper.IParameterCallbacks
22
    {
23
        internal const DbType EnumerableMultiParameter = (DbType)(-1);
24
        private static readonly Dictionary<SqlMapper.Identity, Action<IDbCommand, object>> paramReaderCache = new Dictionary<SqlMapper.Identity, Action<IDbCommand, object>>();
25
        private readonly Dictionary<string, ParamInfo> parameters = new Dictionary<string, ParamInfo>();
26
        private List<object> templates;
27

  
28
        object SqlMapper.IParameterLookup.this[string name] =>
29
            parameters.TryGetValue(name, out ParamInfo param) ? param.Value : null;
30

  
31
        /// <summary>
32
        /// construct a dynamic parameter bag
33
        /// </summary>
34
        public DynamicParameters()
35
        {
36
            RemoveUnused = true;
37
        }
38

  
39
        /// <summary>
40
        /// construct a dynamic parameter bag
41
        /// </summary>
42
        /// <param name="template">can be an anonymous type or a DynamicParameters bag</param>
43
        public DynamicParameters(object template)
44
        {
45
            RemoveUnused = true;
46
            AddDynamicParams(template);
47
        }
48

  
49
        /// <summary>
50
        /// Append a whole object full of params to the dynamic
51
        /// EG: AddDynamicParams(new {A = 1, B = 2}) // will add property A and B to the dynamic
52
        /// </summary>
53
        /// <param name="param"></param>
54
        public void AddDynamicParams(object param)
55
        {
56
            var obj = param;
57
            if (obj != null)
58
            {
59
                if (obj is DynamicParameters subDynamic)
60
                {
61
                    if (subDynamic.parameters != null)
62
                    {
63
                        foreach (var kvp in subDynamic.parameters)
64
                        {
65
                            parameters.Add(kvp.Key, kvp.Value);
66
                        }
67
                    }
68

  
69
                    if (subDynamic.templates != null)
70
                    {
71
                        templates ??= new List<object>();
72
                        foreach (var t in subDynamic.templates)
73
                        {
74
                            templates.Add(t);
75
                        }
76
                    }
77
                }
78
                else
79
                {
80
                    if (obj is IEnumerable<KeyValuePair<string, object>> dictionary)
81
                    {
82
                        foreach (var kvp in dictionary)
83
                        {
84
                            Add(kvp.Key, kvp.Value, null, null, null);
85
                        }
86
                    }
87
                    else
88
                    {
89
                        templates ??= new List<object>();
90
                        templates.Add(obj);
91
                    }
92
                }
93
            }
94
        }
95

  
96
        /// <summary>
97
        /// Add a parameter to this dynamic parameter list.
98
        /// </summary>
99
        /// <param name="name">The name of the parameter.</param>
100
        /// <param name="value">The value of the parameter.</param>
101
        /// <param name="dbType">The type of the parameter.</param>
102
        /// <param name="direction">The in or out direction of the parameter.</param>
103
        /// <param name="size">The size of the parameter.</param>
104
        public void Add(string name, object value, DbType? dbType, ParameterDirection? direction, int? size)
105
        {
106
            parameters[Clean(name)] = new ParamInfo
107
            {
108
                Name = name,
109
                Value = value,
110
                ParameterDirection = direction ?? ParameterDirection.Input,
111
                DbType = dbType,
112
                Size = size
113
            };
114
        }
115

  
116
        /// <summary>
117
        /// Add a parameter to this dynamic parameter list.
118
        /// </summary>
119
        /// <param name="name">The name of the parameter.</param>
120
        /// <param name="value">The value of the parameter.</param>
121
        /// <param name="dbType">The type of the parameter.</param>
122
        /// <param name="direction">The in or out direction of the parameter.</param>
123
        /// <param name="size">The size of the parameter.</param>
124
        /// <param name="precision">The precision of the parameter.</param>
125
        /// <param name="scale">The scale of the parameter.</param>
126
        public void Add(string name, object value = null, DbType? dbType = null, ParameterDirection? direction = null, int? size = null, byte? precision = null, byte? scale = null)
127
        {
128
            parameters[Clean(name)] = new ParamInfo
129
            {
130
                Name = name,
131
                Value = value,
132
                ParameterDirection = direction ?? ParameterDirection.Input,
133
                DbType = dbType,
134
                Size = size,
135
                Precision = precision,
136
                Scale = scale
137
            };
138
        }
139

  
140
        private static string Clean(string name)
141
        {
142
            if (!string.IsNullOrEmpty(name))
143
            {
144
                switch (name[0])
145
                {
146
                    case '@':
147
                    case ':':
148
                    case '?':
149
                        return name.Substring(1);
150
                }
151
            }
152
            return name;
153
        }
154

  
155
        void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command, SqlMapper.Identity identity)
156
        {
157
            AddParameters(command, identity);
158
        }
159

  
160
        /// <summary>
161
        /// If true, the command-text is inspected and only values that are clearly used are included on the connection
162
        /// </summary>
163
        public bool RemoveUnused { get; set; }
164

  
165
        internal static bool ShouldSetDbType(DbType? dbType)
166
            => dbType.HasValue && dbType.GetValueOrDefault() != EnumerableMultiParameter;
167

  
168
        internal static bool ShouldSetDbType(DbType dbType)
169
            => dbType != EnumerableMultiParameter; // just in case called with non-nullable
170

  
171
        /// <summary>
172
        /// Add all the parameters needed to the command just before it executes
173
        /// </summary>
174
        /// <param name="command">The raw command prior to execution</param>
175
        /// <param name="identity">Information about the query</param>
176
        protected void AddParameters(IDbCommand command, SqlMapper.Identity identity)
177
        {
178
            var literals = SqlMapper.GetLiteralTokens(identity.sql);
179

  
180
            if (templates != null)
181
            {
182
                foreach (var template in templates)
183
                {
184
                    var newIdent = identity.ForDynamicParameters(template.GetType());
185
                    Action<IDbCommand, object> appender;
186

  
187
                    lock (paramReaderCache)
188
                    {
189
                        if (!paramReaderCache.TryGetValue(newIdent, out appender))
190
                        {
191
                            appender = SqlMapper.CreateParamInfoGenerator(newIdent, true, RemoveUnused, literals);
192
                            paramReaderCache[newIdent] = appender;
193
                        }
194
                    }
195

  
196
                    appender(command, template);
197
                }
198

  
199
                // The parameters were added to the command, but not the
200
                // DynamicParameters until now.
201
                foreach (IDbDataParameter param in command.Parameters)
202
                {
203
                    // If someone makes a DynamicParameters with a template,
204
                    // then explicitly adds a parameter of a matching name,
205
                    // it will already exist in 'parameters'.
206
                    if (!parameters.ContainsKey(param.ParameterName))
207
                    {
208
                        parameters.Add(param.ParameterName, new ParamInfo
209
                        {
210
                            AttachedParam = param,
211
                            CameFromTemplate = true,
212
                            DbType = param.DbType,
213
                            Name = param.ParameterName,
214
                            ParameterDirection = param.Direction,
215
                            Size = param.Size,
216
                            Value = param.Value
217
                        });
218
                    }
219
                }
220

  
221
                // Now that the parameters are added to the command, let's place our output callbacks
222
                var tmp = outputCallbacks;
223
                if (tmp != null)
224
                {
225
                    foreach (var generator in tmp)
226
                    {
227
                        generator();
228
                    }
229
                }
230
            }
231

  
232
            foreach (var param in parameters.Values)
233
            {
234
                if (param.CameFromTemplate) continue;
235

  
236
                var dbType = param.DbType;
237
                var val = param.Value;
238
                string name = Clean(param.Name);
239
                var isCustomQueryParameter = val is SqlMapper.ICustomQueryParameter;
240

  
241
                SqlMapper.ITypeHandler handler = null;
242
                if (dbType == null && val != null && !isCustomQueryParameter)
243
                {
244
#pragma warning disable 618
245
                    dbType = SqlMapper.LookupDbType(val.GetType(), name, true, out handler);
246
#pragma warning disable 618
247
                }
248
                if (isCustomQueryParameter)
249
                {
250
                    ((SqlMapper.ICustomQueryParameter)val).AddParameter(command, name);
251
                }
252
                else if (dbType == EnumerableMultiParameter)
253
                {
254
#pragma warning disable 612, 618
255
                    SqlMapper.PackListParameters(command, name, val);
256
#pragma warning restore 612, 618
257
                }
258
                else
259
                {
260
                    bool add = !command.Parameters.Contains(name);
261
                    IDbDataParameter p;
262
                    if (add)
263
                    {
264
                        p = command.CreateParameter();
265
                        p.ParameterName = name;
266
                    }
267
                    else
268
                    {
269
                        p = (IDbDataParameter)command.Parameters[name];
270
                    }
271

  
272
                    p.Direction = param.ParameterDirection;
273
                    if (handler == null)
274
                    {
275
#pragma warning disable 0618
276
                        p.Value = SqlMapper.SanitizeParameterValue(val);
277
#pragma warning restore 0618
278
                        if (ShouldSetDbType(dbType) && p.DbType != dbType.GetValueOrDefault())
279
                        {
280
                            p.DbType = dbType.GetValueOrDefault();
281
                        }
282
                        var s = val as string;
283
                        if (s?.Length <= DbString.DefaultLength)
284
                        {
285
                            p.Size = DbString.DefaultLength;
286
                        }
287
                        if (param.Size != null) p.Size = param.Size.Value;
288
                        if (param.Precision != null) p.Precision = param.Precision.Value;
289
                        if (param.Scale != null) p.Scale = param.Scale.Value;
290
                    }
291
                    else
292
                    {
293
                        if (ShouldSetDbType(dbType)) p.DbType = dbType.GetValueOrDefault();
294
                        if (param.Size != null) p.Size = param.Size.Value;
295
                        if (param.Precision != null) p.Precision = param.Precision.Value;
296
                        if (param.Scale != null) p.Scale = param.Scale.Value;
297
                        handler.SetValue(p, val ?? DBNull.Value);
298
                    }
299

  
300
                    if (add)
301
                    {
302
                        command.Parameters.Add(p);
303
                    }
304
                    param.AttachedParam = p;
305
                }
306
            }
307

  
308
            // note: most non-privileged implementations would use: this.ReplaceLiterals(command);
309
            if (literals.Count != 0) SqlMapper.ReplaceLiterals(this, command, literals);
310
        }
311

  
312
        /// <summary>
313
        /// All the names of the param in the bag, use Get to yank them out
314
        /// </summary>
315
        public IEnumerable<string> ParameterNames => parameters.Select(p => p.Key);
316

  
317
        /// <summary>
318
        /// Get the value of a parameter
319
        /// </summary>
320
        /// <typeparam name="T"></typeparam>
321
        /// <param name="name"></param>
322
        /// <returns>The value, note DBNull.Value is not returned, instead the value is returned as null</returns>
323
        public T Get<T>(string name)
324
        {
325
            var paramInfo = parameters[Clean(name)];
326
            var attachedParam = paramInfo.AttachedParam;
327
            object val = attachedParam == null ? paramInfo.Value : attachedParam.Value;
328
            if (val == DBNull.Value)
329
            {
330
                if (default(T) != null)
331
                {
332
                    throw new ApplicationException("Attempting to cast a DBNull to a non nullable type! Note that out/return parameters will not have updated values until the data stream completes (after the 'foreach' for Query(..., buffered: false), or after the GridReader has been disposed for QueryMultiple)");
333
                }
334
                return default;
335
            }
336
            return (T)val;
337
        }
338

  
339
        /// <summary>
340
        /// Allows you to automatically populate a target property/field from output parameters. It actually
341
        /// creates an InputOutput parameter, so you can still pass data in.
342
        /// </summary>
343
        /// <typeparam name="T"></typeparam>
344
        /// <param name="target">The object whose property/field you wish to populate.</param>
345
        /// <param name="expression">A MemberExpression targeting a property/field of the target (or descendant thereof.)</param>
346
        /// <param name="dbType"></param>
347
        /// <param name="size">The size to set on the parameter. Defaults to 0, or DbString.DefaultLength in case of strings.</param>
348
        /// <returns>The DynamicParameters instance</returns>
349
        public DynamicParameters Output<T>(T target, Expression<Func<T, object>> expression, DbType? dbType = null, int? size = null)
350
        {
351
            static void ThrowInvalidChain()
352
                => throw new InvalidOperationException($"Expression must be a property/field chain off of a(n) {typeof(T).Name} instance");
353

  
354
            // Is it even a MemberExpression?
355
#pragma warning disable IDE0019 // Use pattern matching - already complex enough
356
            var lastMemberAccess = expression.Body as MemberExpression;
357
#pragma warning restore IDE0019 // Use pattern matching
358

  
359
            if (lastMemberAccess == null
360
                || (!(lastMemberAccess.Member is PropertyInfo)
361
                    && !(lastMemberAccess.Member is FieldInfo)))
362
            {
363
                if (expression.Body.NodeType == ExpressionType.Convert
364
                    && expression.Body.Type == typeof(object)
365
                    && ((UnaryExpression)expression.Body).Operand is MemberExpression member)
366
                {
367
                    // It's got to be unboxed
368
                    lastMemberAccess = member;
369
                }
370
                else
371
                {
372
                    ThrowInvalidChain();
373
                }
374
            }
375

  
376
            // Does the chain consist of MemberExpressions leading to a ParameterExpression of type T?
377
            MemberExpression diving = lastMemberAccess;
378
            // Retain a list of member names and the member expressions so we can rebuild the chain.
379
            List<string> names = new List<string>();
380
            List<MemberExpression> chain = new List<MemberExpression>();
381

  
382
            do
383
            {
384
                // Insert the names in the right order so expression
385
                // "Post.Author.Name" becomes parameter "PostAuthorName"
386
                names.Insert(0, diving?.Member.Name);
387
                chain.Insert(0, diving);
388

  
389
#pragma warning disable IDE0019 // use pattern matching; this is fine!
390
                var constant = diving?.Expression as ParameterExpression;
391
                diving = diving?.Expression as MemberExpression;
392
#pragma warning restore IDE0019 // use pattern matching
393

  
394
                if (constant is object && constant.Type == typeof(T))
395
                {
396
                    break;
397
                }
398
                else if (diving == null
399
                    || (!(diving.Member is PropertyInfo)
400
                        && !(diving.Member is FieldInfo)))
401
                {
402
                    ThrowInvalidChain();
403
                }
404
            }
405
            while (diving != null);
406

  
407
            var dynamicParamName = string.Concat(names.ToArray());
408

  
409
            // Before we get all emitty...
410
            var lookup = string.Join("|", names.ToArray());
411

  
412
            var cache = CachedOutputSetters<T>.Cache;
413
            var setter = (Action<object, DynamicParameters>)cache[lookup];
414
            if (setter != null) goto MAKECALLBACK;
415

  
416
            // Come on let's build a method, let's build it, let's build it now!
417
            var dm = new DynamicMethod("ExpressionParam" + Guid.NewGuid().ToString(), null, new[] { typeof(object), GetType() }, true);
418
            var il = dm.GetILGenerator();
419

  
420
            il.Emit(OpCodes.Ldarg_0); // [object]
421
            il.Emit(OpCodes.Castclass, typeof(T));    // [T]
422

  
423
            // Count - 1 to skip the last member access
424
            for (var i = 0; i < chain.Count - 1; i++)
425
            {
426
                var member = chain[i].Member;
427

  
428
                if (member is PropertyInfo info)
429
                {
430
                    var get = info.GetGetMethod(true);
431
                    il.Emit(OpCodes.Callvirt, get); // [Member{i}]
432
                }
433
                else // Else it must be a field!
434
                {
435
                    il.Emit(OpCodes.Ldfld, (FieldInfo)member); // [Member{i}]
436
                }
437
            }
438

  
439
            var paramGetter = GetType().GetMethod("Get", new Type[] { typeof(string) }).MakeGenericMethod(lastMemberAccess.Type);
440

  
441
            il.Emit(OpCodes.Ldarg_1); // [target] [DynamicParameters]
442
            il.Emit(OpCodes.Ldstr, dynamicParamName); // [target] [DynamicParameters] [ParamName]
443
            il.Emit(OpCodes.Callvirt, paramGetter); // [target] [value], it's already typed thanks to generic method
444

  
445
            // GET READY
446
            var lastMember = lastMemberAccess.Member;
447
            if (lastMember is PropertyInfo property)
448
            {
449
                var set = property.GetSetMethod(true);
450
                il.Emit(OpCodes.Callvirt, set); // SET
451
            }
452
            else
453
            {
454
                il.Emit(OpCodes.Stfld, (FieldInfo)lastMember); // SET
455
            }
456

  
457
            il.Emit(OpCodes.Ret); // GO
458

  
459
            setter = (Action<object, DynamicParameters>)dm.CreateDelegate(typeof(Action<object, DynamicParameters>));
460
            lock (cache)
461
            {
462
                cache[lookup] = setter;
463
            }
464

  
465
            // Queue the preparation to be fired off when adding parameters to the DbCommand
466
            MAKECALLBACK:
467
            (outputCallbacks ??= new List<Action>()).Add(() =>
468
            {
469
                // Finally, prep the parameter and attach the callback to it
470
                var targetMemberType = lastMemberAccess?.Type;
471
                int sizeToSet = (!size.HasValue && targetMemberType == typeof(string)) ? DbString.DefaultLength : size ?? 0;
472

  
473
                if (parameters.TryGetValue(dynamicParamName, out ParamInfo parameter))
474
                {
475
                    parameter.ParameterDirection = parameter.AttachedParam.Direction = ParameterDirection.InputOutput;
476

  
477
                    if (parameter.AttachedParam.Size == 0)
478
                    {
479
                        parameter.Size = parameter.AttachedParam.Size = sizeToSet;
480
                    }
481
                }
482
                else
483
                {
484
                    // CameFromTemplate property would not apply here because this new param
485
                    // Still needs to be added to the command
486
                    Add(dynamicParamName, expression.Compile().Invoke(target), dbType, ParameterDirection.InputOutput, sizeToSet);
487
                }
488

  
489
                parameter = parameters[dynamicParamName];
490
                parameter.OutputCallback = setter;
491
                parameter.OutputTarget = target;
492
            });
493

  
494
            return this;
495
        }
496

  
497
        private List<Action> outputCallbacks;
498

  
499
        void SqlMapper.IParameterCallbacks.OnCompleted()
500
        {
501
            foreach (var param in from p in parameters select p.Value)
502
            {
503
                param.OutputCallback?.Invoke(param.OutputTarget, this);
504
            }
505
        }
506
    }
507
}
ConvertService/ServiceBase/Markus.Service.DataBase.Dapper/dbTypeConvert.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Data;
4
using System.Linq;
5
using System.Text;
6
using System.Threading.Tasks;
7

  
8
namespace Markus.Service.DataBase
9
{
10
    public static class dbTypeConvert
11
    {
12
        private static readonly List<TypeItem> _typeMap;
13

  
14
        //private static Dictionary<Type, DbType> _typeMap;
15
        //private static Dictionary<Type, NpgsqlTypes.NpgsqlDbType> _npgSQLtypeMap;
16

  
17
        static dbTypeConvert()
18
        {
19
            _typeMap = new List<TypeItem>();
20
            _typeMap.Add(new TypeItem{ PostgreSQL = "int8",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Bigint,DbType = DbType.Int64,Type = typeof(Int64)});
21
            _typeMap.Add(new TypeItem{ PostgreSQL = "bool",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Boolean,DbType = DbType.Boolean,Type = typeof(Boolean)});
22
            _typeMap.Add(new TypeItem{ PostgreSQL = "bytea",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Bytea,DbType = DbType.Binary,Type = typeof(Byte[])});
23
            _typeMap.Add(new TypeItem{ PostgreSQL = "date",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Date,DbType = DbType.Date,Type = typeof(DateTime)});
24
            _typeMap.Add(new TypeItem{ PostgreSQL = "float8",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Double,DbType = DbType.Double,Type = typeof(Double)});
25
            _typeMap.Add(new TypeItem{ PostgreSQL = "int4",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Integer,DbType = DbType.Int32,Type = typeof(Int32)});
26
            _typeMap.Add(new TypeItem{ PostgreSQL = "money",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Money,DbType = DbType.Decimal,Type = typeof(Decimal)});
27
            _typeMap.Add(new TypeItem{ PostgreSQL = "numeric",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Numeric,DbType = DbType.Decimal,Type = typeof(Decimal)});
28
            _typeMap.Add(new TypeItem{ PostgreSQL = "float4",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Real,DbType = DbType.Single,Type = typeof(Single)});
29
            _typeMap.Add(new TypeItem{ PostgreSQL = "int2",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Smallint,DbType = DbType.Int16,Type = typeof(Int16)});
30
            _typeMap.Add(new TypeItem{ PostgreSQL = "text",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Text,DbType = DbType.String,Type = typeof(String)});
31
            _typeMap.Add(new TypeItem{ PostgreSQL = "time",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Time,DbType = DbType.Time,Type = typeof(DateTime)});
32
            _typeMap.Add(new TypeItem{ PostgreSQL = "timetz",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Time,DbType = DbType.Time,Type = typeof(DateTime)});
33
            _typeMap.Add(new TypeItem{ PostgreSQL = "timestamp",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Timestamp,DbType = DbType.DateTime,Type = typeof(DateTime)});
34
            _typeMap.Add(new TypeItem{ PostgreSQL = "timestamptz",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.TimestampTz,DbType = DbType.DateTime,Type = typeof(DateTime)});
35
            _typeMap.Add(new TypeItem{ PostgreSQL = "interval",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Interval,DbType = DbType.Object,Type = typeof(TimeSpan)});
36
            _typeMap.Add(new TypeItem{ PostgreSQL = "varchar",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Varchar,DbType = DbType.String,Type = typeof(String)});
37
            _typeMap.Add(new TypeItem{ PostgreSQL = "inet",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Inet,DbType = DbType.Object,Type = typeof(System.Net.IPAddress) });
38
            _typeMap.Add(new TypeItem{ PostgreSQL = "bit",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Bit,DbType = DbType.Boolean,Type = typeof(Boolean)});
39
            _typeMap.Add(new TypeItem{ PostgreSQL = "uuid",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Uuid,DbType = DbType.Guid,Type = typeof(Guid)});
40
            _typeMap.Add(new TypeItem{ PostgreSQL = "array",NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Array,DbType = DbType.Object,Type = typeof(Array)});
41
            //DefaultMap();
42
            //npgSQLMap();
43
        }
44

  
45
        public static NpgsqlTypes.NpgsqlDbType? GetNpgsqlDbType(DbType dbType)
46
        {
47
            var type = _typeMap.Find(x => x.DbType == dbType);
48

  
49
            if (type == null)
50
            {
51
                return null;
52
            }
53
            else
54
            {
55
                return type.NpgsqlDbType;
56
            }
57
        }
58

  
59
        public static NpgsqlTypes.NpgsqlDbType? GetNpgsqlDbType(Type csharpType)
60
        {
61
            var type = _typeMap.Find(x => x.Type == csharpType);
62

  
63
            if (type == null)
64
            {
65
                return null;
66
            }
67
            else
68
            {
69
                return type.NpgsqlDbType;
70
            }
71
        }
72

  
73

  
74
        //private static void DefaultMap()
75
        //{ 
76
        //     _typeMap = new Dictionary<Type, DbType>();
77
        //    _typeMap[typeof(byte)] = DbType.Byte;
78
        //    _typeMap[typeof(sbyte)] = DbType.SByte;
79
        //    _typeMap[typeof(short)] = DbType.Int16;
80
        //    _typeMap[typeof(ushort)] = DbType.UInt16;
81
        //    _typeMap[typeof(int)] = DbType.Int32;
82
        //    _typeMap[typeof(uint)] = DbType.UInt32;
83
        //    _typeMap[typeof(long)] = DbType.Int64;
84
        //    _typeMap[typeof(ulong)] = DbType.UInt64;
85
        //    _typeMap[typeof(float)] = DbType.Single;
86
        //    _typeMap[typeof(double)] = DbType.Double;
87
        //    _typeMap[typeof(decimal)] = DbType.Decimal;
88
        //    _typeMap[typeof(bool)] = DbType.Boolean;
89
        //    _typeMap[typeof(string)] = DbType.String;
90
        //    _typeMap[typeof(char)] = DbType.StringFixedLength;
91
        //    _typeMap[typeof(Guid)] = DbType.Guid;
92
        //    _typeMap[typeof(DateTime)] = DbType.DateTime;
93
        //    _typeMap[typeof(DateTimeOffset)] = DbType.DateTimeOffset;
94
        //    _typeMap[typeof(byte[])] = DbType.Binary;
95
        //    _typeMap[typeof(byte?)] = DbType.Byte;
96
        //    _typeMap[typeof(sbyte?)] = DbType.SByte;
97
        //    _typeMap[typeof(short?)] = DbType.Int16;
98
        //    _typeMap[typeof(ushort?)] = DbType.UInt16;
99
        //    _typeMap[typeof(int?)] = DbType.Int32;
100
        //    _typeMap[typeof(uint?)] = DbType.UInt32;
101
        //    _typeMap[typeof(long?)] = DbType.Int64;
102
        //    _typeMap[typeof(ulong?)] = DbType.UInt64;
103
        //    _typeMap[typeof(float?)] = DbType.Single;
104
        //    _typeMap[typeof(double?)] = DbType.Double;
105
        //    _typeMap[typeof(decimal?)] = DbType.Decimal;
106
        //    _typeMap[typeof(bool?)] = DbType.Boolean;
107
        //    _typeMap[typeof(char?)] = DbType.StringFixedLength;
108
        //    _typeMap[typeof(Guid?)] = DbType.Guid;
109
        //    _typeMap[typeof(DateTime?)] = DbType.DateTime;
110
        //    _typeMap[typeof(DateTimeOffset?)] = DbType.DateTimeOffset;
111
        //    _typeMap[typeof(DBNull)] = DbType.String;
112
        //}
113

  
114
        //private static void npgSQLMap()
115
        //{
116
        //    _npgSQLtypeMap = new Dictionary<Type, NpgsqlTypes.NpgsqlDbType>();
117

  
118
        //    _npgSQLtypeMap[typeof(Int64)] = NpgsqlTypes.NpgsqlDbType.Bigint;
119
        //    _npgSQLtypeMap[typeof(bool)] =  NpgsqlTypes.NpgsqlDbType.Smallint;
120
        //    _npgSQLtypeMap[typeof(byte[])] = NpgsqlTypes.NpgsqlDbType.Bytea;
121
        //    _npgSQLtypeMap[typeof(DateTime)] = NpgsqlTypes.NpgsqlDbType.Date;
122
        //    _npgSQLtypeMap[typeof(double)] = NpgsqlTypes.NpgsqlDbType.Double;
123
        //    _npgSQLtypeMap[typeof(Int32)] = NpgsqlTypes.NpgsqlDbType.Integer;
124
        //    _npgSQLtypeMap[typeof(decimal)] = NpgsqlTypes.NpgsqlDbType.Money;
125
        //    _npgSQLtypeMap[typeof(decimal)] = NpgsqlTypes.NpgsqlDbType.Numeric;
126
        //    _npgSQLtypeMap[typeof(Single)] = NpgsqlTypes.NpgsqlDbType.Real;
127
        //    _npgSQLtypeMap[typeof(Int16)] = NpgsqlTypes.NpgsqlDbType.Smallint;
128
        //    _npgSQLtypeMap[typeof(string)] = NpgsqlTypes.NpgsqlDbType.Text;
129
        //    _npgSQLtypeMap[typeof(DateTime)] = NpgsqlTypes.NpgsqlDbType.Time;
130
        //    _npgSQLtypeMap[typeof(DateTime)] = NpgsqlTypes.NpgsqlDbType.Time;
131
        //    _npgSQLtypeMap[typeof(DateTime)] = NpgsqlTypes.NpgsqlDbType.Timestamp;
132
        //    _npgSQLtypeMap[typeof(DateTime)] = NpgsqlTypes.NpgsqlDbType.TimestampTz;
133

  
134
        //    _npgSQLtypeMap[typeof(TimeSpan)] = NpgsqlTypes.NpgsqlDbType.Interval;
135
        //    _npgSQLtypeMap[typeof(string)] = NpgsqlTypes.NpgsqlDbType.Varchar;
136
        //    _npgSQLtypeMap[typeof(System.Net.IPAddress)] = NpgsqlTypes.NpgsqlDbType.Inet;
137
        //    _npgSQLtypeMap[typeof(bool)] = NpgsqlTypes.NpgsqlDbType.Bit;
138
        //    _npgSQLtypeMap[typeof(Guid)] = NpgsqlTypes.NpgsqlDbType.Uuid;
139
        //    _npgSQLtypeMap[typeof(Array)] = NpgsqlTypes.NpgsqlDbType.Array;
140

  
141
        //}
142

  
143

  
144
        private class TypeItem
145
        {
146
            public string PostgreSQL { get; set; }
147

  
148
            public NpgsqlTypes.NpgsqlDbType NpgsqlDbType { get; set; }
149
            public System.Data.DbType DbType { get; set; }
150
            public Type Type { get; set;}
151
        }
152
    }
153

  
154
    
155
}
ConvertService/ServiceBase/Markus.Service.DataBase.Test/TestBaseMSSQL.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
6

  
7
namespace Markus.Service.DataBase.Test
8
{
9
    public class TestBaseMSSQL
10
    {
11
        public string ConnectionStr = "Data Source=cloud.devdoftech.co.kr,7777;Initial Catalog=markus;Persist Security Info=True;User ID=doftech;Password=dof1073#";
12
        public Markus.Service.DataBase.DBMSType dbtype = DBMSType.MSSQL;
13
        public string ProjectNo = "000000";
14
        public string docUri = "test://test";
15

  
16
    }
17
}
ConvertService/ServiceBase/Markus.Service.DataBase.Test/TestBasePG.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
6

  
7
namespace Markus.Service.DataBase.Test
8
{
9
    public class TestBasePG
10
    {
11
        public string ConnectionStr = "Host=192.168.0.37;Port=49164;Database=markus;User ID=doftech;Password=dof1073#";
12
        public Markus.Service.DataBase.DBMSType dbtype = DBMSType.POSTGRESQL;
13
        public string ProjectNo = "000000";
14
        public string docUri = "test://test";
15

  
16
    }
17
}
ConvertService/ServiceBase/Markus.Service.WcfClient/Properties/DataSources/Markus.Service.DataBase.Entities.ConvertDoc.datasource
1
<?xml version="1.0" encoding="utf-8"?>
2
<!--
3
    This file is automatically generated by Visual Studio .Net. It is 
4
    used to store generic object data source configuration information.  
5
    Renaming the file extension or editing the content of this file may   
6
    cause the file to be unrecognizable by the program.
7
-->
8
<GenericObjectDataSource DisplayName="ConvertDoc" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
9
   <TypeInfo>Markus.Service.DataBase.Entities.ConvertDoc, Markus.Service.DataBase.Dapper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
10
</GenericObjectDataSource>

내보내기 Unified diff

클립보드 이미지 추가 (최대 크기: 500 MB)