Selaa lähdekoodia

[WebApiUtils] tests

feature/authentication-tests
Robin Thoni 9 vuotta sitten
vanhempi
commit
37a9d109cb

+ 21
- 0
WebAPiUtils-test/BusinessManager/ValuesBusiness.cs Näytä tiedosto

@@ -0,0 +1,21 @@
1
+using System.Collections.Generic;
2
+using iiie.Logs.DBO;
3
+using WebAPiUtils_test.DataAccess;
4
+using WebAPiUtils_test.DBO;
5
+
6
+namespace WebAPiUtils_test.BusinessManager
7
+{
8
+    public class ValuesBusiness
9
+    {
10
+        public static OpResult<ValuesDbo> Get(long id)
11
+        {
12
+            //return ValuesManager.Get(id);
13
+            return ValuesManager.GetByIdDbo(id);
14
+        }
15
+
16
+        public static OpResult<IEnumerable<ValuesDbo>> Contains(string text)
17
+        {
18
+            return ValuesManager.Contains(text);
19
+        }
20
+    }
21
+}

+ 11
- 2
WebAPiUtils-test/Controllers/ValuesController.cs Näytä tiedosto

@@ -1,6 +1,8 @@
1 1
 using System;
2 2
 using System.Collections.Generic;
3 3
 using System.Web.Http;
4
+using iiie.WebApiUtils.BusinessManager;
5
+using WebAPiUtils_test.BusinessManager;
4 6
 using WebAPiUtils_test.DBO;
5 7
 
6 8
 namespace WebAPiUtils_test.Controllers
@@ -14,9 +16,16 @@ namespace WebAPiUtils_test.Controllers
14 16
         }
15 17
 
16 18
         // GET api/values/5
17
-        public string Get(int id)
19
+        public ValuesDbo Get(int id)
18 20
         {
19
-            return "value";
21
+            return BMRHandler<ValuesDbo>.Handle(ValuesBusiness.Get(id), Request);
22
+        }
23
+
24
+        [HttpGet]
25
+        [Route("api/values/contains")]
26
+        public IEnumerable<ValuesDbo> Contains(string text)
27
+        {
28
+            return BMRHandler<IEnumerable<ValuesDbo>>.Handle(ValuesBusiness.Contains(text), Request);
20 29
         }
21 30
 
22 31
         // POST api/values

+ 12
- 0
WebAPiUtils-test/DBO/ValuesDbo.cs Näytä tiedosto

@@ -0,0 +1,12 @@
1
+
2
+namespace WebAPiUtils_test.DBO
3
+{
4
+    public class ValuesDbo
5
+    {
6
+        public long Id { get; set; }
7
+
8
+        public string MyString { get; set; }
9
+
10
+        public int MyInt { get; set; }
11
+    }
12
+}

+ 30
- 0
WebAPiUtils-test/DataAccess/SqlServerManager.Context.cs Näytä tiedosto

@@ -0,0 +1,30 @@
1
+//------------------------------------------------------------------------------
2
+// <auto-generated>
3
+//     This code was generated from a template.
4
+//
5
+//     Manual changes to this file may cause unexpected behavior in your application.
6
+//     Manual changes to this file will be overwritten if the code is regenerated.
7
+// </auto-generated>
8
+//------------------------------------------------------------------------------
9
+
10
+namespace WebAPiUtils_test.DataAccess
11
+{
12
+    using System;
13
+    using System.Data.Entity;
14
+    using System.Data.Entity.Infrastructure;
15
+    
16
+    public partial class SqlServerManagerEntities : DbContext
17
+    {
18
+        public SqlServerManagerEntities()
19
+            : base("name=SqlServerManagerEntities")
20
+        {
21
+        }
22
+    
23
+        protected override void OnModelCreating(DbModelBuilder modelBuilder)
24
+        {
25
+            throw new UnintentionalCodeFirstException();
26
+        }
27
+    
28
+        public virtual DbSet<T_SqlManager> T_SqlManager { get; set; }
29
+    }
30
+}

+ 636
- 0
WebAPiUtils-test/DataAccess/SqlServerManager.Context.tt Näytä tiedosto

@@ -0,0 +1,636 @@
1
+<#@ template language="C#" debug="false" hostspecific="true"#>
2
+<#@ include file="EF6.Utility.CS.ttinclude"#><#@
3
+ output extension=".cs"#><#
4
+
5
+const string inputFile = @"SqlServerManager.edmx";
6
+var textTransform = DynamicTextTransformation.Create(this);
7
+var code = new CodeGenerationTools(this);
8
+var ef = new MetadataTools(this);
9
+var typeMapper = new TypeMapper(code, ef, textTransform.Errors);
10
+var loader = new EdmMetadataLoader(textTransform.Host, textTransform.Errors);
11
+var itemCollection = loader.CreateEdmItemCollection(inputFile);
12
+var modelNamespace = loader.GetModelNamespace(inputFile);
13
+var codeStringGenerator = new CodeStringGenerator(code, typeMapper, ef);
14
+
15
+var container = itemCollection.OfType<EntityContainer>().FirstOrDefault();
16
+if (container == null)
17
+{
18
+    return string.Empty;
19
+}
20
+#>
21
+//------------------------------------------------------------------------------
22
+// <auto-generated>
23
+// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine1")#>
24
+//
25
+// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine2")#>
26
+// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine3")#>
27
+// </auto-generated>
28
+//------------------------------------------------------------------------------
29
+
30
+<#
31
+
32
+var codeNamespace = code.VsNamespaceSuggestion();
33
+if (!String.IsNullOrEmpty(codeNamespace))
34
+{
35
+#>
36
+namespace <#=code.EscapeNamespace(codeNamespace)#>
37
+{
38
+<#
39
+    PushIndent("    ");
40
+}
41
+
42
+#>
43
+using System;
44
+using System.Data.Entity;
45
+using System.Data.Entity.Infrastructure;
46
+<#
47
+if (container.FunctionImports.Any())
48
+{
49
+#>
50
+using System.Data.Entity.Core.Objects;
51
+using System.Linq;
52
+<#
53
+}
54
+#>
55
+
56
+<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
57
+{
58
+    public <#=code.Escape(container)#>()
59
+        : base("name=<#=container.Name#>")
60
+    {
61
+<#
62
+if (!loader.IsLazyLoadingEnabled(container))
63
+{
64
+#>
65
+        this.Configuration.LazyLoadingEnabled = false;
66
+<#
67
+}
68
+
69
+foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())
70
+{
71
+    // Note: the DbSet members are defined below such that the getter and
72
+    // setter always have the same accessibility as the DbSet definition
73
+    if (Accessibility.ForReadOnlyProperty(entitySet) != "public")
74
+    {
75
+#>
76
+        <#=codeStringGenerator.DbSetInitializer(entitySet)#>
77
+<#
78
+    }
79
+}
80
+#>
81
+    }
82
+
83
+    protected override void OnModelCreating(DbModelBuilder modelBuilder)
84
+    {
85
+        throw new UnintentionalCodeFirstException();
86
+    }
87
+
88
+<#
89
+    foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())
90
+    {
91
+#>
92
+    <#=codeStringGenerator.DbSet(entitySet)#>
93
+<#
94
+    }
95
+
96
+    foreach (var edmFunction in container.FunctionImports)
97
+    {
98
+        WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: false);
99
+    }
100
+#>
101
+}
102
+<#
103
+
104
+if (!String.IsNullOrEmpty(codeNamespace))
105
+{
106
+    PopIndent();
107
+#>
108
+}
109
+<#
110
+}
111
+#>
112
+<#+
113
+
114
+private void WriteFunctionImport(TypeMapper typeMapper, CodeStringGenerator codeStringGenerator, EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
115
+{
116
+    if (typeMapper.IsComposable(edmFunction))
117
+    {
118
+#>
119
+
120
+    [DbFunction("<#=edmFunction.NamespaceName#>", "<#=edmFunction.Name#>")]
121
+    <#=codeStringGenerator.ComposableFunctionMethod(edmFunction, modelNamespace)#>
122
+    {
123
+<#+
124
+        codeStringGenerator.WriteFunctionParameters(edmFunction, WriteFunctionParameter);
125
+#>
126
+        <#=codeStringGenerator.ComposableCreateQuery(edmFunction, modelNamespace)#>
127
+    }
128
+<#+
129
+    }
130
+    else
131
+    {
132
+#>
133
+
134
+    <#=codeStringGenerator.FunctionMethod(edmFunction, modelNamespace, includeMergeOption)#>
135
+    {
136
+<#+
137
+        codeStringGenerator.WriteFunctionParameters(edmFunction, WriteFunctionParameter);
138
+#>
139
+        <#=codeStringGenerator.ExecuteFunction(edmFunction, modelNamespace, includeMergeOption)#>
140
+    }
141
+<#+
142
+        if (typeMapper.GenerateMergeOptionFunction(edmFunction, includeMergeOption))
143
+        {
144
+            WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: true);
145
+        }
146
+    }
147
+}
148
+
149
+public void WriteFunctionParameter(string name, string isNotNull, string notNullInit, string nullInit)
150
+{
151
+#>
152
+        var <#=name#> = <#=isNotNull#> ?
153
+            <#=notNullInit#> :
154
+            <#=nullInit#>;
155
+
156
+<#+
157
+}
158
+
159
+public const string TemplateId = "CSharp_DbContext_Context_EF6";
160
+
161
+public class CodeStringGenerator
162
+{
163
+    private readonly CodeGenerationTools _code;
164
+    private readonly TypeMapper _typeMapper;
165
+    private readonly MetadataTools _ef;
166
+
167
+    public CodeStringGenerator(CodeGenerationTools code, TypeMapper typeMapper, MetadataTools ef)
168
+    {
169
+        ArgumentNotNull(code, "code");
170
+        ArgumentNotNull(typeMapper, "typeMapper");
171
+        ArgumentNotNull(ef, "ef");
172
+
173
+        _code = code;
174
+        _typeMapper = typeMapper;
175
+        _ef = ef;
176
+    }
177
+
178
+    public string Property(EdmProperty edmProperty)
179
+    {
180
+        return string.Format(
181
+            CultureInfo.InvariantCulture,
182
+            "{0} {1} {2} {{ {3}get; {4}set; }}",
183
+            Accessibility.ForProperty(edmProperty),
184
+            _typeMapper.GetTypeName(edmProperty.TypeUsage),
185
+            _code.Escape(edmProperty),
186
+            _code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
187
+            _code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
188
+    }
189
+
190
+    public string NavigationProperty(NavigationProperty navProp)
191
+    {
192
+        var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType());
193
+        return string.Format(
194
+            CultureInfo.InvariantCulture,
195
+            "{0} {1} {2} {{ {3}get; {4}set; }}",
196
+            AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)),
197
+            navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
198
+            _code.Escape(navProp),
199
+            _code.SpaceAfter(Accessibility.ForGetter(navProp)),
200
+            _code.SpaceAfter(Accessibility.ForSetter(navProp)));
201
+    }
202
+    
203
+    public string AccessibilityAndVirtual(string accessibility)
204
+    {
205
+        return accessibility + (accessibility != "private" ? " virtual" : "");
206
+    }
207
+    
208
+    public string EntityClassOpening(EntityType entity)
209
+    {
210
+        return string.Format(
211
+            CultureInfo.InvariantCulture,
212
+            "{0} {1}partial class {2}{3}",
213
+            Accessibility.ForType(entity),
214
+            _code.SpaceAfter(_code.AbstractOption(entity)),
215
+            _code.Escape(entity),
216
+            _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)));
217
+    }
218
+    
219
+    public string EnumOpening(SimpleType enumType)
220
+    {
221
+        return string.Format(
222
+            CultureInfo.InvariantCulture,
223
+            "{0} enum {1} : {2}",
224
+            Accessibility.ForType(enumType),
225
+            _code.Escape(enumType),
226
+            _code.Escape(_typeMapper.UnderlyingClrType(enumType)));
227
+        }
228
+    
229
+    public void WriteFunctionParameters(EdmFunction edmFunction, Action<string, string, string, string> writeParameter)
230
+    {
231
+        var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
232
+        foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable))
233
+        {
234
+            var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null";
235
+            var notNullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", " + parameter.FunctionParameterName + ")";
236
+            var nullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", typeof(" + TypeMapper.FixNamespaces(parameter.RawClrTypeName) + "))";
237
+            writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit);
238
+        }
239
+    }
240
+    
241
+    public string ComposableFunctionMethod(EdmFunction edmFunction, string modelNamespace)
242
+    {
243
+        var parameters = _typeMapper.GetParameters(edmFunction);
244
+        
245
+        return string.Format(
246
+            CultureInfo.InvariantCulture,
247
+            "{0} IQueryable<{1}> {2}({3})",
248
+            AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
249
+            _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
250
+            _code.Escape(edmFunction),
251
+            string.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray()));
252
+    }
253
+    
254
+    public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace)
255
+    {
256
+        var parameters = _typeMapper.GetParameters(edmFunction);
257
+        
258
+        return string.Format(
259
+            CultureInfo.InvariantCulture,
260
+            "return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});",
261
+            _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
262
+            edmFunction.NamespaceName,
263
+            edmFunction.Name,
264
+            string.Join(", ", parameters.Select(p => "@" + p.EsqlParameterName).ToArray()),
265
+            _code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray())));
266
+    }
267
+    
268
+    public string FunctionMethod(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
269
+    {
270
+        var parameters = _typeMapper.GetParameters(edmFunction);
271
+        var returnType = _typeMapper.GetReturnType(edmFunction);
272
+
273
+        var paramList = String.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray());
274
+        if (includeMergeOption)
275
+        {
276
+            paramList = _code.StringAfter(paramList, ", ") + "MergeOption mergeOption";
277
+        }
278
+
279
+        return string.Format(
280
+            CultureInfo.InvariantCulture,
281
+            "{0} {1} {2}({3})",
282
+            AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
283
+            returnType == null ? "int" : "ObjectResult<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
284
+            _code.Escape(edmFunction),
285
+            paramList);
286
+    }
287
+    
288
+    public string ExecuteFunction(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
289
+    {
290
+        var parameters = _typeMapper.GetParameters(edmFunction);
291
+        var returnType = _typeMapper.GetReturnType(edmFunction);
292
+
293
+        var callParams = _code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()));
294
+        if (includeMergeOption)
295
+        {
296
+            callParams = ", mergeOption" + callParams;
297
+        }
298
+        
299
+        return string.Format(
300
+            CultureInfo.InvariantCulture,
301
+            "return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction{0}(\"{1}\"{2});",
302
+            returnType == null ? "" : "<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
303
+            edmFunction.Name,
304
+            callParams);
305
+    }
306
+    
307
+    public string DbSet(EntitySet entitySet)
308
+    {
309
+        return string.Format(
310
+            CultureInfo.InvariantCulture,
311
+            "{0} virtual DbSet<{1}> {2} {{ get; set; }}",
312
+            Accessibility.ForReadOnlyProperty(entitySet),
313
+            _typeMapper.GetTypeName(entitySet.ElementType),
314
+            _code.Escape(entitySet));
315
+    }
316
+
317
+    public string DbSetInitializer(EntitySet entitySet)
318
+    {
319
+        return string.Format(
320
+            CultureInfo.InvariantCulture,
321
+            "{0} = Set<{1}>();",
322
+            _code.Escape(entitySet),
323
+            _typeMapper.GetTypeName(entitySet.ElementType));
324
+    }
325
+
326
+    public string UsingDirectives(bool inHeader, bool includeCollections = true)
327
+    {
328
+        return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
329
+            ? string.Format(
330
+                CultureInfo.InvariantCulture,
331
+                "{0}using System;{1}" +
332
+                "{2}",
333
+                inHeader ? Environment.NewLine : "",
334
+                includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "",
335
+                inHeader ? "" : Environment.NewLine)
336
+            : "";
337
+    }
338
+}
339
+
340
+public class TypeMapper
341
+{
342
+    private const string ExternalTypeNameAttributeName = @"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName";
343
+
344
+    private readonly System.Collections.IList _errors;
345
+    private readonly CodeGenerationTools _code;
346
+    private readonly MetadataTools _ef;
347
+
348
+    public static string FixNamespaces(string typeName)
349
+    {
350
+        return typeName.Replace("System.Data.Spatial.", "System.Data.Entity.Spatial.");
351
+    }
352
+
353
+    public TypeMapper(CodeGenerationTools code, MetadataTools ef, System.Collections.IList errors)
354
+    {
355
+        ArgumentNotNull(code, "code");
356
+        ArgumentNotNull(ef, "ef");
357
+        ArgumentNotNull(errors, "errors");
358
+
359
+        _code = code;
360
+        _ef = ef;
361
+        _errors = errors;
362
+    }
363
+
364
+    public string GetTypeName(TypeUsage typeUsage)
365
+    {
366
+        return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace: null);
367
+    }
368
+
369
+    public string GetTypeName(EdmType edmType)
370
+    {
371
+        return GetTypeName(edmType, isNullable: null, modelNamespace: null);
372
+    }
373
+
374
+    public string GetTypeName(TypeUsage typeUsage, string modelNamespace)
375
+    {
376
+        return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace);
377
+    }
378
+
379
+    public string GetTypeName(EdmType edmType, string modelNamespace)
380
+    {
381
+        return GetTypeName(edmType, isNullable: null, modelNamespace: modelNamespace);
382
+    }
383
+
384
+    public string GetTypeName(EdmType edmType, bool? isNullable, string modelNamespace)
385
+    {
386
+        if (edmType == null)
387
+        {
388
+            return null;
389
+        }
390
+
391
+        var collectionType = edmType as CollectionType;
392
+        if (collectionType != null)
393
+        {
394
+            return String.Format(CultureInfo.InvariantCulture, "ICollection<{0}>", GetTypeName(collectionType.TypeUsage, modelNamespace));
395
+        }
396
+
397
+        var typeName = _code.Escape(edmType.MetadataProperties
398
+                                .Where(p => p.Name == ExternalTypeNameAttributeName)
399
+                                .Select(p => (string)p.Value)
400
+                                .FirstOrDefault())
401
+            ?? (modelNamespace != null && edmType.NamespaceName != modelNamespace ?
402
+                _code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType)) :
403
+                _code.Escape(edmType));
404
+
405
+        if (edmType is StructuralType)
406
+        {
407
+            return typeName;
408
+        }
409
+
410
+        if (edmType is SimpleType)
411
+        {
412
+            var clrType = UnderlyingClrType(edmType);
413
+            if (!IsEnumType(edmType))
414
+            {
415
+                typeName = _code.Escape(clrType);
416
+            }
417
+
418
+            typeName = FixNamespaces(typeName);
419
+
420
+            return clrType.IsValueType && isNullable == true ?
421
+                String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>", typeName) :
422
+                typeName;
423
+        }
424
+
425
+        throw new ArgumentException("edmType");
426
+    }
427
+    
428
+    public Type UnderlyingClrType(EdmType edmType)
429
+    {
430
+        ArgumentNotNull(edmType, "edmType");
431
+
432
+        var primitiveType = edmType as PrimitiveType;
433
+        if (primitiveType != null)
434
+        {
435
+            return primitiveType.ClrEquivalentType;
436
+        }
437
+
438
+        if (IsEnumType(edmType))
439
+        {
440
+            return GetEnumUnderlyingType(edmType).ClrEquivalentType;
441
+        }
442
+
443
+        return typeof(object);
444
+    }
445
+    
446
+    public object GetEnumMemberValue(MetadataItem enumMember)
447
+    {
448
+        ArgumentNotNull(enumMember, "enumMember");
449
+        
450
+        var valueProperty = enumMember.GetType().GetProperty("Value");
451
+        return valueProperty == null ? null : valueProperty.GetValue(enumMember, null);
452
+    }
453
+    
454
+    public string GetEnumMemberName(MetadataItem enumMember)
455
+    {
456
+        ArgumentNotNull(enumMember, "enumMember");
457
+        
458
+        var nameProperty = enumMember.GetType().GetProperty("Name");
459
+        return nameProperty == null ? null : (string)nameProperty.GetValue(enumMember, null);
460
+    }
461
+
462
+    public System.Collections.IEnumerable GetEnumMembers(EdmType enumType)
463
+    {
464
+        ArgumentNotNull(enumType, "enumType");
465
+
466
+        var membersProperty = enumType.GetType().GetProperty("Members");
467
+        return membersProperty != null 
468
+            ? (System.Collections.IEnumerable)membersProperty.GetValue(enumType, null)
469
+            : Enumerable.Empty<MetadataItem>();
470
+    }
471
+    
472
+    public bool EnumIsFlags(EdmType enumType)
473
+    {
474
+        ArgumentNotNull(enumType, "enumType");
475
+        
476
+        var isFlagsProperty = enumType.GetType().GetProperty("IsFlags");
477
+        return isFlagsProperty != null && (bool)isFlagsProperty.GetValue(enumType, null);
478
+    }
479
+
480
+    public bool IsEnumType(GlobalItem edmType)
481
+    {
482
+        ArgumentNotNull(edmType, "edmType");
483
+
484
+        return edmType.GetType().Name == "EnumType";
485
+    }
486
+
487
+    public PrimitiveType GetEnumUnderlyingType(EdmType enumType)
488
+    {
489
+        ArgumentNotNull(enumType, "enumType");
490
+
491
+        return (PrimitiveType)enumType.GetType().GetProperty("UnderlyingType").GetValue(enumType, null);
492
+    }
493
+
494
+    public string CreateLiteral(object value)
495
+    {
496
+        if (value == null || value.GetType() != typeof(TimeSpan))
497
+        {
498
+            return _code.CreateLiteral(value);
499
+        }
500
+
501
+        return string.Format(CultureInfo.InvariantCulture, "new TimeSpan({0})", ((TimeSpan)value).Ticks);
502
+    }
503
+    
504
+    public bool VerifyCaseInsensitiveTypeUniqueness(IEnumerable<string> types, string sourceFile)
505
+    {
506
+        ArgumentNotNull(types, "types");
507
+        ArgumentNotNull(sourceFile, "sourceFile");
508
+        
509
+        var hash = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
510
+        if (types.Any(item => !hash.Add(item)))
511
+        {
512
+            _errors.Add(
513
+                new CompilerError(sourceFile, -1, -1, "6023",
514
+                    String.Format(CultureInfo.CurrentCulture, CodeGenerationTools.GetResourceString("Template_CaseInsensitiveTypeConflict"))));
515
+            return false;
516
+        }
517
+        return true;
518
+    }
519
+    
520
+    public IEnumerable<SimpleType> GetEnumItemsToGenerate(IEnumerable<GlobalItem> itemCollection)
521
+    {
522
+        return GetItemsToGenerate<SimpleType>(itemCollection)
523
+            .Where(e => IsEnumType(e));
524
+    }
525
+    
526
+    public IEnumerable<T> GetItemsToGenerate<T>(IEnumerable<GlobalItem> itemCollection) where T: EdmType
527
+    {
528
+        return itemCollection
529
+            .OfType<T>()
530
+            .Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName))
531
+            .OrderBy(i => i.Name);
532
+    }
533
+
534
+    public IEnumerable<string> GetAllGlobalItems(IEnumerable<GlobalItem> itemCollection)
535
+    {
536
+        return itemCollection
537
+            .Where(i => i is EntityType || i is ComplexType || i is EntityContainer || IsEnumType(i))
538
+            .Select(g => GetGlobalItemName(g));
539
+    }
540
+
541
+    public string GetGlobalItemName(GlobalItem item)
542
+    {
543
+        if (item is EdmType)
544
+        {
545
+            return ((EdmType)item).Name;
546
+        }
547
+        else
548
+        {
549
+            return ((EntityContainer)item).Name;
550
+        }
551
+    }
552
+
553
+    public IEnumerable<EdmProperty> GetSimpleProperties(EntityType type)
554
+    {
555
+        return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
556
+    }
557
+    
558
+    public IEnumerable<EdmProperty> GetSimpleProperties(ComplexType type)
559
+    {
560
+        return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
561
+    }
562
+    
563
+    public IEnumerable<EdmProperty> GetComplexProperties(EntityType type)
564
+    {
565
+        return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
566
+    }
567
+    
568
+    public IEnumerable<EdmProperty> GetComplexProperties(ComplexType type)
569
+    {
570
+        return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
571
+    }
572
+
573
+    public IEnumerable<EdmProperty> GetPropertiesWithDefaultValues(EntityType type)
574
+    {
575
+        return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null);
576
+    }
577
+    
578
+    public IEnumerable<EdmProperty> GetPropertiesWithDefaultValues(ComplexType type)
579
+    {
580
+        return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null);
581
+    }
582
+
583
+    public IEnumerable<NavigationProperty> GetNavigationProperties(EntityType type)
584
+    {
585
+        return type.NavigationProperties.Where(np => np.DeclaringType == type);
586
+    }
587
+    
588
+    public IEnumerable<NavigationProperty> GetCollectionNavigationProperties(EntityType type)
589
+    {
590
+        return type.NavigationProperties.Where(np => np.DeclaringType == type && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many);
591
+    }
592
+    
593
+    public FunctionParameter GetReturnParameter(EdmFunction edmFunction)
594
+    {
595
+        ArgumentNotNull(edmFunction, "edmFunction");
596
+
597
+        var returnParamsProperty = edmFunction.GetType().GetProperty("ReturnParameters");
598
+        return returnParamsProperty == null
599
+            ? edmFunction.ReturnParameter
600
+            : ((IEnumerable<FunctionParameter>)returnParamsProperty.GetValue(edmFunction, null)).FirstOrDefault();
601
+    }
602
+
603
+    public bool IsComposable(EdmFunction edmFunction)
604
+    {
605
+        ArgumentNotNull(edmFunction, "edmFunction");
606
+
607
+        var isComposableProperty = edmFunction.GetType().GetProperty("IsComposableAttribute");
608
+        return isComposableProperty != null && (bool)isComposableProperty.GetValue(edmFunction, null);
609
+    }
610
+
611
+    public IEnumerable<FunctionImportParameter> GetParameters(EdmFunction edmFunction)
612
+    {
613
+        return FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
614
+    }
615
+
616
+    public TypeUsage GetReturnType(EdmFunction edmFunction)
617
+    {
618
+        var returnParam = GetReturnParameter(edmFunction);
619
+        return returnParam == null ? null : _ef.GetElementType(returnParam.TypeUsage);
620
+    }
621
+    
622
+    public bool GenerateMergeOptionFunction(EdmFunction edmFunction, bool includeMergeOption)
623
+    {
624
+        var returnType = GetReturnType(edmFunction);
625
+        return !includeMergeOption && returnType != null && returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType;
626
+    }
627
+}
628
+
629
+public static void ArgumentNotNull<T>(T arg, string name) where T : class
630
+{
631
+    if (arg == null)
632
+    {
633
+        throw new ArgumentNullException(name);
634
+    }
635
+}
636
+#>

+ 10
- 0
WebAPiUtils-test/DataAccess/SqlServerManager.Designer.cs Näytä tiedosto

@@ -0,0 +1,10 @@
1
+// T4 code generation is enabled for model 'C:\Users\robin.thoni\Documents\nuget-3ie\WebAPiUtils-test\DataAccess\SqlServerManager.edmx'. 
2
+// To enable legacy code generation, change the value of the 'Code Generation Strategy' designer
3
+// property to 'Legacy ObjectContext'. This property is available in the Properties Window when the model
4
+// is open in the designer.
5
+
6
+// If no context and entity classes have been generated, it may be because you created an empty model but
7
+// have not yet chosen which version of Entity Framework to use. To generate a context class and entity
8
+// classes for your model, open the model in the designer, right-click on the designer surface, and
9
+// select 'Update Model from Database...', 'Generate Database from Model...', or 'Add Code Generation
10
+// Item...'.

+ 9
- 0
WebAPiUtils-test/DataAccess/SqlServerManager.cs Näytä tiedosto

@@ -0,0 +1,9 @@
1
+//------------------------------------------------------------------------------
2
+// <auto-generated>
3
+//     This code was generated from a template.
4
+//
5
+//     Manual changes to this file may cause unexpected behavior in your application.
6
+//     Manual changes to this file will be overwritten if the code is regenerated.
7
+// </auto-generated>
8
+//------------------------------------------------------------------------------
9
+

+ 72
- 0
WebAPiUtils-test/DataAccess/SqlServerManager.edmx Näytä tiedosto

@@ -0,0 +1,72 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
3
+  <!-- EF Runtime content -->
4
+  <edmx:Runtime>
5
+    <!-- SSDL content -->
6
+    <edmx:StorageModels>
7
+    <Schema Namespace="Model.Store" Provider="System.Data.SqlClient" ProviderManifestToken="2012" Alias="Self" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl">
8
+        <EntityType Name="T_SqlManager">
9
+          <Key>
10
+            <PropertyRef Name="id" />
11
+          </Key>
12
+          <Property Name="id" Type="bigint" StoreGeneratedPattern="Identity" Nullable="false" />
13
+          <Property Name="my_string" Type="varchar" MaxLength="50" Nullable="false" />
14
+          <Property Name="my_int" Type="int" Nullable="false" />
15
+        </EntityType>
16
+        <EntityContainer Name="ModelStoreContainer">
17
+          <EntitySet Name="T_SqlManager" EntityType="Self.T_SqlManager" Schema="dbo" store:Type="Tables" />
18
+        </EntityContainer>
19
+      </Schema></edmx:StorageModels>
20
+    <!-- CSDL content -->
21
+    <edmx:ConceptualModels>
22
+      <Schema Namespace="Model" Alias="Self" annotation:UseStrongSpatialTypes="false" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
23
+        <EntityContainer Name="SqlServerManagerEntities" annotation:LazyLoadingEnabled="true">
24
+          <EntitySet Name="T_SqlManager" EntityType="Model.T_SqlManager" />
25
+        </EntityContainer>
26
+        <EntityType Name="T_SqlManager">
27
+          <Key>
28
+            <PropertyRef Name="id" />
29
+          </Key>
30
+          <Property Name="id" Type="Int64" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
31
+          <Property Name="my_string" Type="String" Nullable="false" MaxLength="50" FixedLength="false" Unicode="false" />
32
+          <Property Name="my_int" Type="Int32" Nullable="false" />
33
+        </EntityType>
34
+      </Schema>
35
+    </edmx:ConceptualModels>
36
+    <!-- C-S mapping content -->
37
+    <edmx:Mappings>
38
+      <Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2009/11/mapping/cs">
39
+        <EntityContainerMapping StorageEntityContainer="ModelStoreContainer" CdmEntityContainer="SqlServerManagerEntities">
40
+          <EntitySetMapping Name="T_SqlManager">
41
+            <EntityTypeMapping TypeName="Model.T_SqlManager">
42
+              <MappingFragment StoreEntitySet="T_SqlManager">
43
+                <ScalarProperty Name="my_int" ColumnName="my_int" />
44
+                <ScalarProperty Name="my_string" ColumnName="my_string" />
45
+                <ScalarProperty Name="id" ColumnName="id" />
46
+              </MappingFragment>
47
+            </EntityTypeMapping>
48
+          </EntitySetMapping>
49
+        </EntityContainerMapping>
50
+      </Mapping>
51
+    </edmx:Mappings>
52
+  </edmx:Runtime>
53
+  <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
54
+  <Designer xmlns="http://schemas.microsoft.com/ado/2009/11/edmx">
55
+    <Connection>
56
+      <DesignerInfoPropertySet>
57
+        <DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
58
+      </DesignerInfoPropertySet>
59
+    </Connection>
60
+    <Options>
61
+      <DesignerInfoPropertySet>
62
+        <DesignerProperty Name="ValidateOnBuild" Value="true" />
63
+        <DesignerProperty Name="EnablePluralization" Value="false" />
64
+        <DesignerProperty Name="IncludeForeignKeysInModel" Value="true" />
65
+        <DesignerProperty Name="UseLegacyProvider" Value="false" />
66
+        <DesignerProperty Name="CodeGenerationStrategy" Value="None" />
67
+      </DesignerInfoPropertySet>
68
+    </Options>
69
+    <!-- Diagram content (shape and connector positions) -->
70
+    <Diagrams></Diagrams>
71
+  </Designer>
72
+</edmx:Edmx>

+ 12
- 0
WebAPiUtils-test/DataAccess/SqlServerManager.edmx.diagram Näytä tiedosto

@@ -0,0 +1,12 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
3
+ <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
4
+  <edmx:Designer xmlns="http://schemas.microsoft.com/ado/2009/11/edmx">
5
+    <!-- Diagram content (shape and connector positions) -->
6
+    <edmx:Diagrams>
7
+      <Diagram DiagramId="08dc5c61470647c385ff700da7502692" Name="Diagram1">
8
+        <EntityTypeShape EntityType="Model.T_SqlManager" Width="1.5" PointX="0.75" PointY="0.75" />
9
+      </Diagram>
10
+    </edmx:Diagrams>
11
+  </edmx:Designer>
12
+</edmx:Edmx>

+ 726
- 0
WebAPiUtils-test/DataAccess/SqlServerManager.tt Näytä tiedosto

@@ -0,0 +1,726 @@
1
+<#@ template language="C#" debug="false" hostspecific="true"#>
2
+<#@ include file="EF6.Utility.CS.ttinclude"#><#@ 
3
+ output extension=".cs"#><#
4
+
5
+const string inputFile = @"SqlServerManager.edmx";
6
+var textTransform = DynamicTextTransformation.Create(this);
7
+var code = new CodeGenerationTools(this);
8
+var ef = new MetadataTools(this);
9
+var typeMapper = new TypeMapper(code, ef, textTransform.Errors);
10
+var	fileManager = EntityFrameworkTemplateFileManager.Create(this);
11
+var itemCollection = new EdmMetadataLoader(textTransform.Host, textTransform.Errors).CreateEdmItemCollection(inputFile);
12
+var codeStringGenerator = new CodeStringGenerator(code, typeMapper, ef);
13
+
14
+if (!typeMapper.VerifyCaseInsensitiveTypeUniqueness(typeMapper.GetAllGlobalItems(itemCollection), inputFile))
15
+{
16
+    return string.Empty;
17
+}
18
+
19
+WriteHeader(codeStringGenerator, fileManager);
20
+
21
+foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>(itemCollection))
22
+{
23
+    fileManager.StartNewFile(entity.Name + ".cs");
24
+    BeginNamespace(code);
25
+#>
26
+<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
27
+<#=codeStringGenerator.EntityClassOpening(entity)#>
28
+{
29
+<#
30
+    var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(entity);
31
+    var collectionNavigationProperties = typeMapper.GetCollectionNavigationProperties(entity);
32
+    var complexProperties = typeMapper.GetComplexProperties(entity);
33
+
34
+    if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any())
35
+    {
36
+#>
37
+    public <#=code.Escape(entity)#>()
38
+    {
39
+<#
40
+        foreach (var edmProperty in propertiesWithDefaultValues)
41
+        {
42
+#>
43
+        this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
44
+<#
45
+        }
46
+
47
+        foreach (var navigationProperty in collectionNavigationProperties)
48
+        {
49
+#>
50
+        this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
51
+<#
52
+        }
53
+
54
+        foreach (var complexProperty in complexProperties)
55
+        {
56
+#>
57
+        this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
58
+<#
59
+        }
60
+#>
61
+    }
62
+
63
+<#
64
+    }
65
+
66
+    var simpleProperties = typeMapper.GetSimpleProperties(entity);
67
+    if (simpleProperties.Any())
68
+    {
69
+        foreach (var edmProperty in simpleProperties)
70
+        {
71
+#>
72
+    <#=codeStringGenerator.Property(edmProperty)#>
73
+<#
74
+        }
75
+    }
76
+
77
+    if (complexProperties.Any())
78
+    {
79
+#>
80
+
81
+<#
82
+        foreach(var complexProperty in complexProperties)
83
+        {
84
+#>
85
+    <#=codeStringGenerator.Property(complexProperty)#>
86
+<#
87
+        }
88
+    }
89
+
90
+    var navigationProperties = typeMapper.GetNavigationProperties(entity);
91
+    if (navigationProperties.Any())
92
+    {
93
+#>
94
+
95
+<#
96
+        foreach (var navigationProperty in navigationProperties)
97
+        {
98
+#>
99
+    <#=codeStringGenerator.NavigationProperty(navigationProperty)#>
100
+<#
101
+        }
102
+    }
103
+#>
104
+}
105
+<#
106
+    EndNamespace(code);
107
+}
108
+
109
+foreach (var complex in typeMapper.GetItemsToGenerate<ComplexType>(itemCollection))
110
+{
111
+    fileManager.StartNewFile(complex.Name + ".cs");
112
+    BeginNamespace(code);
113
+#>
114
+<#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)#>
115
+<#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#>
116
+{
117
+<#
118
+    var complexProperties = typeMapper.GetComplexProperties(complex);
119
+    var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(complex);
120
+
121
+    if (propertiesWithDefaultValues.Any() || complexProperties.Any())
122
+    {
123
+#>
124
+    public <#=code.Escape(complex)#>()
125
+    {
126
+<#
127
+        foreach (var edmProperty in propertiesWithDefaultValues)
128
+        {
129
+#>
130
+        this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
131
+<#
132
+        }
133
+
134
+        foreach (var complexProperty in complexProperties)
135
+        {
136
+#>
137
+        this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
138
+<#
139
+        }
140
+#>
141
+    }
142
+
143
+<#
144
+    }
145
+
146
+    var simpleProperties = typeMapper.GetSimpleProperties(complex);
147
+    if (simpleProperties.Any())
148
+    {
149
+        foreach(var edmProperty in simpleProperties)
150
+        {
151
+#>
152
+    <#=codeStringGenerator.Property(edmProperty)#>
153
+<#
154
+        }
155
+    }
156
+
157
+    if (complexProperties.Any())
158
+    {
159
+#>
160
+
161
+<#
162
+        foreach(var edmProperty in complexProperties)
163
+        {
164
+#>
165
+    <#=codeStringGenerator.Property(edmProperty)#>
166
+<#
167
+        }
168
+    }
169
+#>
170
+}
171
+<#
172
+    EndNamespace(code);
173
+}
174
+
175
+foreach (var enumType in typeMapper.GetEnumItemsToGenerate(itemCollection))
176
+{
177
+    fileManager.StartNewFile(enumType.Name + ".cs");
178
+    BeginNamespace(code);
179
+#>
180
+<#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)#>
181
+<#
182
+    if (typeMapper.EnumIsFlags(enumType))
183
+    {
184
+#>
185
+[Flags]
186
+<#
187
+    }
188
+#>
189
+<#=codeStringGenerator.EnumOpening(enumType)#>
190
+{
191
+<#
192
+    var foundOne = false;
193
+    
194
+    foreach (MetadataItem member in typeMapper.GetEnumMembers(enumType))
195
+    {
196
+        foundOne = true;
197
+#>
198
+    <#=code.Escape(typeMapper.GetEnumMemberName(member))#> = <#=typeMapper.GetEnumMemberValue(member)#>,
199
+<#
200
+    }
201
+
202
+    if (foundOne)
203
+    {
204
+        this.GenerationEnvironment.Remove(this.GenerationEnvironment.Length - 3, 1);
205
+    }
206
+#>
207
+}
208
+<#
209
+    EndNamespace(code);
210
+}
211
+
212
+fileManager.Process();
213
+
214
+#>
215
+<#+
216
+
217
+public void WriteHeader(CodeStringGenerator codeStringGenerator, EntityFrameworkTemplateFileManager fileManager)
218
+{
219
+    fileManager.StartHeader();
220
+#>
221
+//------------------------------------------------------------------------------
222
+// <auto-generated>
223
+// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine1")#>
224
+//
225
+// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine2")#>
226
+// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine3")#>
227
+// </auto-generated>
228
+//------------------------------------------------------------------------------
229
+<#=codeStringGenerator.UsingDirectives(inHeader: true)#>
230
+<#+
231
+    fileManager.EndBlock();
232
+}
233
+
234
+public void BeginNamespace(CodeGenerationTools code)
235
+{
236
+    var codeNamespace = code.VsNamespaceSuggestion();
237
+    if (!String.IsNullOrEmpty(codeNamespace))
238
+    {
239
+#>
240
+namespace <#=code.EscapeNamespace(codeNamespace)#>
241
+{
242
+<#+
243
+        PushIndent("    ");
244
+    }
245
+}
246
+
247
+public void EndNamespace(CodeGenerationTools code)
248
+{
249
+    if (!String.IsNullOrEmpty(code.VsNamespaceSuggestion()))
250
+    {
251
+        PopIndent();
252
+#>
253
+}
254
+<#+
255
+    }
256
+}
257
+
258
+public const string TemplateId = "CSharp_DbContext_Types_EF6";
259
+
260
+public class CodeStringGenerator
261
+{
262
+    private readonly CodeGenerationTools _code;
263
+    private readonly TypeMapper _typeMapper;
264
+    private readonly MetadataTools _ef;
265
+
266
+    public CodeStringGenerator(CodeGenerationTools code, TypeMapper typeMapper, MetadataTools ef)
267
+    {
268
+        ArgumentNotNull(code, "code");
269
+        ArgumentNotNull(typeMapper, "typeMapper");
270
+        ArgumentNotNull(ef, "ef");
271
+
272
+        _code = code;
273
+        _typeMapper = typeMapper;
274
+        _ef = ef;
275
+    }
276
+
277
+    public string Property(EdmProperty edmProperty)
278
+    {
279
+        return string.Format(
280
+            CultureInfo.InvariantCulture,
281
+            "{0} {1} {2} {{ {3}get; {4}set; }}",
282
+            Accessibility.ForProperty(edmProperty),
283
+            _typeMapper.GetTypeName(edmProperty.TypeUsage),
284
+            _code.Escape(edmProperty),
285
+            _code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
286
+            _code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
287
+    }
288
+
289
+    public string NavigationProperty(NavigationProperty navProp)
290
+    {
291
+        var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType());
292
+        return string.Format(
293
+            CultureInfo.InvariantCulture,
294
+            "{0} {1} {2} {{ {3}get; {4}set; }}",
295
+            AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)),
296
+            navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
297
+            _code.Escape(navProp),
298
+            _code.SpaceAfter(Accessibility.ForGetter(navProp)),
299
+            _code.SpaceAfter(Accessibility.ForSetter(navProp)));
300
+    }
301
+    
302
+    public string AccessibilityAndVirtual(string accessibility)
303
+    {
304
+        return accessibility + (accessibility != "private" ? " virtual" : "");
305
+    }
306
+    
307
+    public string EntityClassOpening(EntityType entity)
308
+    {
309
+        return string.Format(
310
+            CultureInfo.InvariantCulture,
311
+            "{0} {1}partial class {2}{3}",
312
+            Accessibility.ForType(entity),
313
+            _code.SpaceAfter(_code.AbstractOption(entity)),
314
+            _code.Escape(entity),
315
+            _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)));
316
+    }
317
+    
318
+    public string EnumOpening(SimpleType enumType)
319
+    {
320
+        return string.Format(
321
+            CultureInfo.InvariantCulture,
322
+            "{0} enum {1} : {2}",
323
+            Accessibility.ForType(enumType),
324
+            _code.Escape(enumType),
325
+            _code.Escape(_typeMapper.UnderlyingClrType(enumType)));
326
+        }
327
+    
328
+    public void WriteFunctionParameters(EdmFunction edmFunction, Action<string, string, string, string> writeParameter)
329
+    {
330
+        var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
331
+        foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable))
332
+        {
333
+            var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null";
334
+            var notNullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", " + parameter.FunctionParameterName + ")";
335
+            var nullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", typeof(" + TypeMapper.FixNamespaces(parameter.RawClrTypeName) + "))";
336
+            writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit);
337
+        }
338
+    }
339
+    
340
+    public string ComposableFunctionMethod(EdmFunction edmFunction, string modelNamespace)
341
+    {
342
+        var parameters = _typeMapper.GetParameters(edmFunction);
343
+        
344
+        return string.Format(
345
+            CultureInfo.InvariantCulture,
346
+            "{0} IQueryable<{1}> {2}({3})",
347
+            AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
348
+            _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
349
+            _code.Escape(edmFunction),
350
+            string.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray()));
351
+    }
352
+    
353
+    public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace)
354
+    {
355
+        var parameters = _typeMapper.GetParameters(edmFunction);
356
+        
357
+        return string.Format(
358
+            CultureInfo.InvariantCulture,
359
+            "return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});",
360
+            _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
361
+            edmFunction.NamespaceName,
362
+            edmFunction.Name,
363
+            string.Join(", ", parameters.Select(p => "@" + p.EsqlParameterName).ToArray()),
364
+            _code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray())));
365
+    }
366
+    
367
+    public string FunctionMethod(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
368
+    {
369
+        var parameters = _typeMapper.GetParameters(edmFunction);
370
+        var returnType = _typeMapper.GetReturnType(edmFunction);
371
+
372
+        var paramList = String.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray());
373
+        if (includeMergeOption)
374
+        {
375
+            paramList = _code.StringAfter(paramList, ", ") + "MergeOption mergeOption";
376
+        }
377
+
378
+        return string.Format(
379
+            CultureInfo.InvariantCulture,
380
+            "{0} {1} {2}({3})",
381
+            AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
382
+            returnType == null ? "int" : "ObjectResult<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
383
+            _code.Escape(edmFunction),
384
+            paramList);
385
+    }
386
+    
387
+    public string ExecuteFunction(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
388
+    {
389
+        var parameters = _typeMapper.GetParameters(edmFunction);
390
+        var returnType = _typeMapper.GetReturnType(edmFunction);
391
+
392
+        var callParams = _code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()));
393
+        if (includeMergeOption)
394
+        {
395
+            callParams = ", mergeOption" + callParams;
396
+        }
397
+        
398
+        return string.Format(
399
+            CultureInfo.InvariantCulture,
400
+            "return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction{0}(\"{1}\"{2});",
401
+            returnType == null ? "" : "<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
402
+            edmFunction.Name,
403
+            callParams);
404
+    }
405
+    
406
+    public string DbSet(EntitySet entitySet)
407
+    {
408
+        return string.Format(
409
+            CultureInfo.InvariantCulture,
410
+            "{0} virtual DbSet<{1}> {2} {{ get; set; }}",
411
+            Accessibility.ForReadOnlyProperty(entitySet),
412
+            _typeMapper.GetTypeName(entitySet.ElementType),
413
+            _code.Escape(entitySet));
414
+    }
415
+
416
+    public string UsingDirectives(bool inHeader, bool includeCollections = true)
417
+    {
418
+        return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
419
+            ? string.Format(
420
+                CultureInfo.InvariantCulture,
421
+                "{0}using System;{1}" +
422
+                "{2}",
423
+                inHeader ? Environment.NewLine : "",
424
+                includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "",
425
+                inHeader ? "" : Environment.NewLine)
426
+            : "";
427
+    }
428
+}
429
+
430
+public class TypeMapper
431
+{
432
+    private const string ExternalTypeNameAttributeName = @"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName";
433
+
434
+    private readonly System.Collections.IList _errors;
435
+    private readonly CodeGenerationTools _code;
436
+    private readonly MetadataTools _ef;
437
+
438
+    public TypeMapper(CodeGenerationTools code, MetadataTools ef, System.Collections.IList errors)
439
+    {
440
+        ArgumentNotNull(code, "code");
441
+        ArgumentNotNull(ef, "ef");
442
+        ArgumentNotNull(errors, "errors");
443
+
444
+        _code = code;
445
+        _ef = ef;
446
+        _errors = errors;
447
+    }
448
+
449
+    public static string FixNamespaces(string typeName)
450
+    {
451
+        return typeName.Replace("System.Data.Spatial.", "System.Data.Entity.Spatial.");
452
+    }
453
+
454
+    public string GetTypeName(TypeUsage typeUsage)
455
+    {
456
+        return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace: null);
457
+    }
458
+
459
+    public string GetTypeName(EdmType edmType)
460
+    {
461
+        return GetTypeName(edmType, isNullable: null, modelNamespace: null);
462
+    }
463
+
464
+    public string GetTypeName(TypeUsage typeUsage, string modelNamespace)
465
+    {
466
+        return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace);
467
+    }
468
+
469
+    public string GetTypeName(EdmType edmType, string modelNamespace)
470
+    {
471
+        return GetTypeName(edmType, isNullable: null, modelNamespace: modelNamespace);
472
+    }
473
+
474
+    public string GetTypeName(EdmType edmType, bool? isNullable, string modelNamespace)
475
+    {
476
+        if (edmType == null)
477
+        {
478
+            return null;
479
+        }
480
+
481
+        var collectionType = edmType as CollectionType;
482
+        if (collectionType != null)
483
+        {
484
+            return String.Format(CultureInfo.InvariantCulture, "ICollection<{0}>", GetTypeName(collectionType.TypeUsage, modelNamespace));
485
+        }
486
+
487
+        var typeName = _code.Escape(edmType.MetadataProperties
488
+                                .Where(p => p.Name == ExternalTypeNameAttributeName)
489
+                                .Select(p => (string)p.Value)
490
+                                .FirstOrDefault())
491
+            ?? (modelNamespace != null && edmType.NamespaceName != modelNamespace ?
492
+                _code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType)) :
493
+                _code.Escape(edmType));
494
+
495
+        if (edmType is StructuralType)
496
+        {
497
+            return typeName;
498
+        }
499
+
500
+        if (edmType is SimpleType)
501
+        {
502
+            var clrType = UnderlyingClrType(edmType);
503
+            if (!IsEnumType(edmType))
504
+            {
505
+                typeName = _code.Escape(clrType);
506
+            }
507
+
508
+            typeName = FixNamespaces(typeName);
509
+
510
+            return clrType.IsValueType && isNullable == true ?
511
+                String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>", typeName) :
512
+                typeName;
513
+        }
514
+
515
+        throw new ArgumentException("edmType");
516
+    }
517
+    
518
+    public Type UnderlyingClrType(EdmType edmType)
519
+    {
520
+        ArgumentNotNull(edmType, "edmType");
521
+
522
+        var primitiveType = edmType as PrimitiveType;
523
+        if (primitiveType != null)
524
+        {
525
+            return primitiveType.ClrEquivalentType;
526
+        }
527
+
528
+        if (IsEnumType(edmType))
529
+        {
530
+            return GetEnumUnderlyingType(edmType).ClrEquivalentType;
531
+        }
532
+
533
+        return typeof(object);
534
+    }
535
+    
536
+    public object GetEnumMemberValue(MetadataItem enumMember)
537
+    {
538
+        ArgumentNotNull(enumMember, "enumMember");
539
+        
540
+        var valueProperty = enumMember.GetType().GetProperty("Value");
541
+        return valueProperty == null ? null : valueProperty.GetValue(enumMember, null);
542
+    }
543
+    
544
+    public string GetEnumMemberName(MetadataItem enumMember)
545
+    {
546
+        ArgumentNotNull(enumMember, "enumMember");
547
+        
548
+        var nameProperty = enumMember.GetType().GetProperty("Name");
549
+        return nameProperty == null ? null : (string)nameProperty.GetValue(enumMember, null);
550
+    }
551
+
552
+    public System.Collections.IEnumerable GetEnumMembers(EdmType enumType)
553
+    {
554
+        ArgumentNotNull(enumType, "enumType");
555
+
556
+        var membersProperty = enumType.GetType().GetProperty("Members");
557
+        return membersProperty != null 
558
+            ? (System.Collections.IEnumerable)membersProperty.GetValue(enumType, null)
559
+            : Enumerable.Empty<MetadataItem>();
560
+    }
561
+    
562
+    public bool EnumIsFlags(EdmType enumType)
563
+    {
564
+        ArgumentNotNull(enumType, "enumType");
565
+        
566
+        var isFlagsProperty = enumType.GetType().GetProperty("IsFlags");
567
+        return isFlagsProperty != null && (bool)isFlagsProperty.GetValue(enumType, null);
568
+    }
569
+
570
+    public bool IsEnumType(GlobalItem edmType)
571
+    {
572
+        ArgumentNotNull(edmType, "edmType");
573
+
574
+        return edmType.GetType().Name == "EnumType";
575
+    }
576
+
577
+    public PrimitiveType GetEnumUnderlyingType(EdmType enumType)
578
+    {
579
+        ArgumentNotNull(enumType, "enumType");
580
+
581
+        return (PrimitiveType)enumType.GetType().GetProperty("UnderlyingType").GetValue(enumType, null);
582
+    }
583
+
584
+    public string CreateLiteral(object value)
585
+    {
586
+        if (value == null || value.GetType() != typeof(TimeSpan))
587
+        {
588
+            return _code.CreateLiteral(value);
589
+        }
590
+
591
+        return string.Format(CultureInfo.InvariantCulture, "new TimeSpan({0})", ((TimeSpan)value).Ticks);
592
+    }
593
+    
594
+    public bool VerifyCaseInsensitiveTypeUniqueness(IEnumerable<string> types, string sourceFile)
595
+    {
596
+        ArgumentNotNull(types, "types");
597
+        ArgumentNotNull(sourceFile, "sourceFile");
598
+        
599
+        var hash = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
600
+        if (types.Any(item => !hash.Add(item)))
601
+        {
602
+            _errors.Add(
603
+                new CompilerError(sourceFile, -1, -1, "6023",
604
+                    String.Format(CultureInfo.CurrentCulture, CodeGenerationTools.GetResourceString("Template_CaseInsensitiveTypeConflict"))));
605
+            return false;
606
+        }
607
+        return true;
608
+    }
609
+    
610
+    public IEnumerable<SimpleType> GetEnumItemsToGenerate(IEnumerable<GlobalItem> itemCollection)
611
+    {
612
+        return GetItemsToGenerate<SimpleType>(itemCollection)
613
+            .Where(e => IsEnumType(e));
614
+    }
615
+    
616
+    public IEnumerable<T> GetItemsToGenerate<T>(IEnumerable<GlobalItem> itemCollection) where T: EdmType
617
+    {
618
+        return itemCollection
619
+            .OfType<T>()
620
+            .Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName))
621
+            .OrderBy(i => i.Name);
622
+    }
623
+
624
+    public IEnumerable<string> GetAllGlobalItems(IEnumerable<GlobalItem> itemCollection)
625
+    {
626
+        return itemCollection
627
+            .Where(i => i is EntityType || i is ComplexType || i is EntityContainer || IsEnumType(i))
628
+            .Select(g => GetGlobalItemName(g));
629
+    }
630
+
631
+    public string GetGlobalItemName(GlobalItem item)
632
+    {
633
+        if (item is EdmType)
634
+        {
635
+            return ((EdmType)item).Name;
636
+        }
637
+        else
638
+        {
639
+            return ((EntityContainer)item).Name;
640
+        }
641
+    }
642
+
643
+    public IEnumerable<EdmProperty> GetSimpleProperties(EntityType type)
644
+    {
645
+        return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
646
+    }
647
+    
648
+    public IEnumerable<EdmProperty> GetSimpleProperties(ComplexType type)
649
+    {
650
+        return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
651
+    }
652
+    
653
+    public IEnumerable<EdmProperty> GetComplexProperties(EntityType type)
654
+    {
655
+        return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
656
+    }
657
+    
658
+    public IEnumerable<EdmProperty> GetComplexProperties(ComplexType type)
659
+    {
660
+        return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
661
+    }
662
+
663
+    public IEnumerable<EdmProperty> GetPropertiesWithDefaultValues(EntityType type)
664
+    {
665
+        return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null);
666
+    }
667
+    
668
+    public IEnumerable<EdmProperty> GetPropertiesWithDefaultValues(ComplexType type)
669
+    {
670
+        return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null);
671
+    }
672
+
673
+    public IEnumerable<NavigationProperty> GetNavigationProperties(EntityType type)
674
+    {
675
+        return type.NavigationProperties.Where(np => np.DeclaringType == type);
676
+    }
677
+    
678
+    public IEnumerable<NavigationProperty> GetCollectionNavigationProperties(EntityType type)
679
+    {
680
+        return type.NavigationProperties.Where(np => np.DeclaringType == type && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many);
681
+    }
682
+    
683
+    public FunctionParameter GetReturnParameter(EdmFunction edmFunction)
684
+    {
685
+        ArgumentNotNull(edmFunction, "edmFunction");
686
+
687
+        var returnParamsProperty = edmFunction.GetType().GetProperty("ReturnParameters");
688
+        return returnParamsProperty == null
689
+            ? edmFunction.ReturnParameter
690
+            : ((IEnumerable<FunctionParameter>)returnParamsProperty.GetValue(edmFunction, null)).FirstOrDefault();
691
+    }
692
+
693
+    public bool IsComposable(EdmFunction edmFunction)
694
+    {
695
+        ArgumentNotNull(edmFunction, "edmFunction");
696
+
697
+        var isComposableProperty = edmFunction.GetType().GetProperty("IsComposableAttribute");
698
+        return isComposableProperty != null && (bool)isComposableProperty.GetValue(edmFunction, null);
699
+    }
700
+
701
+    public IEnumerable<FunctionImportParameter> GetParameters(EdmFunction edmFunction)
702
+    {
703
+        return FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
704
+    }
705
+
706
+    public TypeUsage GetReturnType(EdmFunction edmFunction)
707
+    {
708
+        var returnParam = GetReturnParameter(edmFunction);
709
+        return returnParam == null ? null : _ef.GetElementType(returnParam.TypeUsage);
710
+    }
711
+    
712
+    public bool GenerateMergeOptionFunction(EdmFunction edmFunction, bool includeMergeOption)
713
+    {
714
+        var returnType = GetReturnType(edmFunction);
715
+        return !includeMergeOption && returnType != null && returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType;
716
+    }
717
+}
718
+
719
+public static void ArgumentNotNull<T>(T arg, string name) where T : class
720
+{
721
+    if (arg == null)
722
+    {
723
+        throw new ArgumentNullException(name);
724
+    }
725
+}
726
+#>

+ 21
- 0
WebAPiUtils-test/DataAccess/T_SqlManager.cs Näytä tiedosto

@@ -0,0 +1,21 @@
1
+//------------------------------------------------------------------------------
2
+// <auto-generated>
3
+//     This code was generated from a template.
4
+//
5
+//     Manual changes to this file may cause unexpected behavior in your application.
6
+//     Manual changes to this file will be overwritten if the code is regenerated.
7
+// </auto-generated>
8
+//------------------------------------------------------------------------------
9
+
10
+namespace WebAPiUtils_test.DataAccess
11
+{
12
+    using System;
13
+    using System.Collections.Generic;
14
+    
15
+    public partial class T_SqlManager
16
+    {
17
+        public long id { get; set; }
18
+        public string my_string { get; set; }
19
+        public int my_int { get; set; }
20
+    }
21
+}

+ 42
- 0
WebAPiUtils-test/DataAccess/ValuesManager.cs Näytä tiedosto

@@ -0,0 +1,42 @@
1
+using System.Collections.Generic;
2
+using System.Data.Entity;
3
+using System.Security;
4
+using iiie.Logs.DBO;
5
+using iiie.WebApiUtils.BusinessManager;
6
+using WebAPiUtils_test.DBO;
7
+
8
+namespace WebAPiUtils_test.DataAccess
9
+{
10
+    public class ValuesManager : SqlServerManager<T_SqlManager, ValuesDbo, SqlServerManagerEntities, ValuesManager>
11
+    {
12
+        public override DbSet<T_SqlManager> GetTable(SqlServerManagerEntities db)
13
+        {
14
+            return db.T_SqlManager;
15
+        }
16
+
17
+        public override ValuesDbo DbToDbo(T_SqlManager o)
18
+        {
19
+            return new ValuesDbo
20
+            {
21
+                Id = o.id,
22
+                MyInt = o.my_int,
23
+                MyString = o.my_string
24
+            };
25
+        }
26
+
27
+        public override T_SqlManager DboToDb(ValuesDbo o)
28
+        {
29
+            return new T_SqlManager
30
+            {
31
+                id = o.Id,
32
+                my_int = o.MyInt,
33
+                my_string = o.MyString
34
+            };
35
+        }
36
+
37
+        public static OpResult<IEnumerable<ValuesDbo>> Contains(string text)
38
+        {
39
+            return GetMultipleDbo(x => x.my_string.Contains(text));
40
+        }
41
+    }
42
+}

+ 18
- 4
WebAPiUtils-test/Web.config Näytä tiedosto

@@ -43,7 +43,7 @@
43 43
   </loggingConfiguration>
44 44
   <connectionStrings>
45 45
     <add name="Logs-test" connectionString="Server=127.0.0.1;Database=Logs-test;Integrated Security=True" providerName="System.Data.SqlClient" />
46
-  </connectionStrings>
46
+  <add name="SqlServerManagerEntities" connectionString="metadata=res://*/DataAccess.SqlServerManager.csdl|res://*/DataAccess.SqlServerManager.ssdl|res://*/DataAccess.SqlServerManager.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=127.0.0.1;initial catalog=Logs-test;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" /></connectionStrings>
47 47
   <appSettings>
48 48
     <add key="webpages:Version" value="3.0.0.0" />
49 49
     <add key="webpages:Enabled" value="false" />
@@ -54,7 +54,6 @@
54 54
     <compilation debug="true" targetFramework="4.5" />
55 55
     <httpRuntime targetFramework="4.5" />
56 56
   </system.web>
57
-  
58 57
   <runtime>
59 58
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
60 59
       <dependentAssembly>
@@ -81,13 +80,28 @@
81 80
         <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
82 81
         <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
83 82
       </dependentAssembly>
83
+      <dependentAssembly>
84
+        <assemblyIdentity name="EntityFramework" publicKeyToken="b77a5c561934e089" culture="neutral" />
85
+        <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
86
+      </dependentAssembly>
84 87
     </assemblyBinding>
85 88
   </runtime>
86
-<system.webServer>
89
+  <system.webServer>
87 90
     <handlers>
88 91
       <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
89 92
       <remove name="OPTIONSVerbHandler" />
90 93
       <remove name="TRACEVerbHandler" />
91 94
       <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
92 95
     </handlers>
93
-  </system.webServer></configuration>
96
+  </system.webServer>
97
+  <entityFramework>
98
+    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
99
+      <parameters>
100
+        <parameter value="v11.0" />
101
+      </parameters>
102
+    </defaultConnectionFactory>
103
+    <providers>
104
+      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
105
+    </providers>
106
+  </entityFramework>
107
+</configuration>

+ 55
- 1
WebAPiUtils-test/WebAPiUtils-test.csproj Näytä tiedosto

@@ -39,6 +39,18 @@
39 39
     <WarningLevel>4</WarningLevel>
40 40
   </PropertyGroup>
41 41
   <ItemGroup>
42
+    <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
43
+      <HintPath>..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll</HintPath>
44
+      <Private>True</Private>
45
+    </Reference>
46
+    <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
47
+      <HintPath>..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll</HintPath>
48
+      <Private>True</Private>
49
+    </Reference>
50
+    <Reference Include="Logs, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
51
+      <HintPath>..\packages\Logs.dll.1.2.1\lib\net45\Logs.dll</HintPath>
52
+      <Private>True</Private>
53
+    </Reference>
42 54
     <Reference Include="Microsoft.CSharp" />
43 55
     <Reference Include="Microsoft.Practices.EnterpriseLibrary.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
44 56
       <HintPath>..\packages\EnterpriseLibrary.Common.6.0.1304.0\lib\NET45\Microsoft.Practices.EnterpriseLibrary.Common.dll</HintPath>
@@ -62,12 +74,13 @@
62 74
     </Reference>
63 75
     <Reference Include="System" />
64 76
     <Reference Include="System.Data" />
65
-    <Reference Include="System.Data.Entity" />
66 77
     <Reference Include="System.Drawing" />
67 78
     <Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
68 79
       <HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath>
69 80
       <Private>True</Private>
70 81
     </Reference>
82
+    <Reference Include="System.Runtime.Serialization" />
83
+    <Reference Include="System.Security" />
71 84
     <Reference Include="System.Web.Entity" />
72 85
     <Reference Include="System.Web.ApplicationServices" />
73 86
     <Reference Include="System.ComponentModel.DataAnnotations" />
@@ -153,9 +166,30 @@
153 166
     <Compile Include="Areas\HelpPage\SampleGeneration\SampleDirection.cs" />
154 167
     <Compile Include="Areas\HelpPage\SampleGeneration\TextSample.cs" />
155 168
     <Compile Include="Areas\HelpPage\XmlDocumentationProvider.cs" />
169
+    <Compile Include="BusinessManager\ValuesBusiness.cs" />
156 170
     <Compile Include="Controllers\HomeController.cs" />
157 171
     <Compile Include="Controllers\ValuesController.cs" />
172
+    <Compile Include="DataAccess\SqlServerManager.Context.cs">
173
+      <AutoGen>True</AutoGen>
174
+      <DesignTime>True</DesignTime>
175
+      <DependentUpon>SqlServerManager.Context.tt</DependentUpon>
176
+    </Compile>
177
+    <Compile Include="DataAccess\SqlServerManager.cs">
178
+      <AutoGen>True</AutoGen>
179
+      <DesignTime>True</DesignTime>
180
+      <DependentUpon>SqlServerManager.tt</DependentUpon>
181
+    </Compile>
182
+    <Compile Include="DataAccess\SqlServerManager.Designer.cs">
183
+      <AutoGen>True</AutoGen>
184
+      <DesignTime>True</DesignTime>
185
+      <DependentUpon>SqlServerManager.edmx</DependentUpon>
186
+    </Compile>
187
+    <Compile Include="DataAccess\T_SqlManager.cs">
188
+      <DependentUpon>SqlServerManager.tt</DependentUpon>
189
+    </Compile>
190
+    <Compile Include="DataAccess\ValuesManager.cs" />
158 191
     <Compile Include="DBO\MyDbo.cs" />
192
+    <Compile Include="DBO\ValuesDbo.cs" />
159 193
     <Compile Include="Global.asax.cs">
160 194
       <DependentUpon>Global.asax</DependentUpon>
161 195
     </Compile>
@@ -181,6 +215,23 @@
181 215
     <Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\HelpPageApiModel.cshtml" />
182 216
     <Content Include="Areas\HelpPage\Views\Help\DisplayTemplates\ApiGroup.cshtml" />
183 217
     <Content Include="Areas\HelpPage\Views\Help\Api.cshtml" />
218
+    <EntityDeploy Include="DataAccess\SqlServerManager.edmx">
219
+      <Generator>EntityModelCodeGenerator</Generator>
220
+      <LastGenOutput>SqlServerManager.Designer.cs</LastGenOutput>
221
+    </EntityDeploy>
222
+    <Content Include="DataAccess\SqlServerManager.Context.tt">
223
+      <Generator>TextTemplatingFileGenerator</Generator>
224
+      <DependentUpon>SqlServerManager.edmx</DependentUpon>
225
+      <LastGenOutput>SqlServerManager.Context.cs</LastGenOutput>
226
+    </Content>
227
+    <Content Include="DataAccess\SqlServerManager.edmx.diagram">
228
+      <DependentUpon>SqlServerManager.edmx</DependentUpon>
229
+    </Content>
230
+    <Content Include="DataAccess\SqlServerManager.tt">
231
+      <Generator>TextTemplatingFileGenerator</Generator>
232
+      <DependentUpon>SqlServerManager.edmx</DependentUpon>
233
+      <LastGenOutput>SqlServerManager.cs</LastGenOutput>
234
+    </Content>
184 235
     <None Include="Scripts\jquery-1.10.2.intellisense.js" />
185 236
     <Content Include="Scripts\jquery-1.10.2.js" />
186 237
     <Content Include="Scripts\jquery-1.10.2.min.js" />
@@ -217,6 +268,9 @@
217 268
     <Content Include="packages.config" />
218 269
     <None Include="Project_Readme.html" />
219 270
   </ItemGroup>
271
+  <ItemGroup>
272
+    <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
273
+  </ItemGroup>
220 274
   <PropertyGroup>
221 275
     <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
222 276
     <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

+ 2
- 0
WebAPiUtils-test/packages.config Näytä tiedosto

@@ -6,7 +6,9 @@
6 6
   <package id="EnterpriseLibrary.Data" version="6.0.1304.0" targetFramework="net45" />
7 7
   <package id="EnterpriseLibrary.Logging" version="6.0.1304.0" targetFramework="net45" />
8 8
   <package id="EnterpriseLibrary.Logging.Database" version="6.0.1304.0" targetFramework="net45" />
9
+  <package id="EntityFramework" version="6.1.3" targetFramework="net45" />
9 10
   <package id="jQuery" version="1.10.2" targetFramework="net45" />
11
+  <package id="Logs.dll" version="1.2.1" targetFramework="net45" />
10 12
   <package id="Microsoft.AspNet.Mvc" version="5.0.0" targetFramework="net45" />
11 13
   <package id="Microsoft.AspNet.Razor" version="3.0.0" targetFramework="net45" />
12 14
   <package id="Microsoft.AspNet.Web.Optimization" version="1.1.1" targetFramework="net45" />

+ 1
- 1
WebApiUtils/BusinessManager/BMRHandler.cs Näytä tiedosto

@@ -36,7 +36,7 @@ namespace iiie.WebApiUtils.BusinessManager
36 36
         /// <returns>The error string</returns>
37 37
         public static string OpResultToString(OpResult<T> result)
38 38
         {
39
-            if (result)
39
+            if (result.PublicDetails != null)
40 40
                 return result.PublicDetails;
41 41
 
42 42
             if (result.Status == ResultStatus.LoginError)

+ 221
- 0
WebApiUtils/BusinessManager/SqlServerManager.cs Näytä tiedosto

@@ -0,0 +1,221 @@
1
+using System;
2
+using System.Collections.Generic;
3
+using System.Data.Entity;
4
+using System.Linq;
5
+using System.Linq.Expressions;
6
+using iiie.Logs.DataAccess;
7
+using iiie.Logs.DBO;
8
+using System.Linq.Dynamic;
9
+
10
+namespace iiie.WebApiUtils.BusinessManager
11
+{
12
+    /// <summary>
13
+    /// Helper for SQL Server data access
14
+    /// </summary>
15
+    public abstract class SqlServerManager<TDbObject, TDbo, TEntities, TThis>
16
+        where TDbObject : class
17
+        where TEntities : DbContext, new()
18
+        where TThis : SqlServerManager<TDbObject, TDbo, TEntities, TThis>,  new()
19
+    {
20
+        private class DbObjectId
21
+        {
22
+            public long id { get; set; }
23
+        }
24
+
25
+        /// <summary>
26
+        /// Return the table to be used
27
+        /// </summary>
28
+        /// <param name="db">The database</param>
29
+        /// <returns>The table instance</returns>
30
+        public abstract DbSet<TDbObject> GetTable(TEntities db);
31
+
32
+        public abstract TDbo DbToDbo(TDbObject obj);
33
+
34
+        public abstract TDbObject DboToDb(TDbo obj);
35
+
36
+        /// <summary>
37
+        /// Return the database table to use
38
+        /// </summary>
39
+        /// <param name="db">The database instance</param>
40
+        /// <returns>The table</returns>
41
+        public static DbSet<TDbObject> GetTableStatic(TEntities db)
42
+        {
43
+            var type = new TThis();
44
+            return type.GetTable(db);
45
+        }
46
+
47
+        /// <summary>
48
+        /// Helper to convert DB object to DBO
49
+        /// </summary>
50
+        /// <param name="res">The result to convert</param>
51
+        /// <returns>The DBO object</returns>
52
+        public static OpResult<TDbo> DbToDboStatic(OpResult<TDbObject> res)
53
+        {
54
+            if (!res)
55
+                return OpResult<TDbo>.Error(res);
56
+            var obj = new TThis();
57
+            return OpResult<TDbo>.Ok(obj.DbToDbo(res.Data));
58
+        }
59
+        
60
+        /// <summary>
61
+        /// Helper to convert DBO object to DB
62
+        /// </summary>
63
+        /// <param name="res">The result to convert</param>
64
+        /// <returns>The DB object</returns>
65
+        public static OpResult<TDbObject> DboToDbStatic(OpResult<TDbo> res)
66
+        {
67
+            if (!res)
68
+                return OpResult<TDbObject>.Error(res);
69
+            var obj = new TThis();
70
+            return OpResult<TDbObject>.Ok(obj.DboToDb(res.Data));
71
+        }
72
+
73
+        /// <summary>
74
+        /// Helper to convert DB object to DBO
75
+        /// </summary>
76
+        /// <param name="res">The result to convert</param>
77
+        /// <returns>The DBO object</returns>
78
+        public static TDbo DbToDboStatic(TDbObject res)
79
+        {
80
+            var obj = new TThis();
81
+            return obj.DbToDbo(res);
82
+        }
83
+        
84
+        /// <summary>
85
+        /// Helper to convert DBO object to DB
86
+        /// </summary>
87
+        /// <param name="res">The result to convert</param>
88
+        /// <returns>The DB object</returns>
89
+        public static TDbObject DboToDbStatic(TDbo res)
90
+        {
91
+            var obj = new TThis();
92
+            return obj.DboToDb(res);
93
+        }
94
+
95
+        /// <summary>
96
+        /// Execute SQL quries in try catch
97
+        /// </summary>
98
+        /// <param name="func">The queries to be performed</param>
99
+        /// <returns>The result or an error</returns>
100
+        public static OpResult<U> Execute<U>(Func<TEntities, DbSet<TDbObject>, OpResult<U>> func)
101
+        {
102
+            try
103
+            {
104
+                using (var db = new TEntities())
105
+                {
106
+                    var table = GetTableStatic(db);
107
+                    return func(db, table);
108
+                }
109
+            }
110
+            catch (Exception e)
111
+            {
112
+                return Logger.Error<U>(ResultStatus.DBError, e);
113
+            }
114
+        }
115
+
116
+        /// <summary>
117
+        /// Get a single DB object matching the predicate
118
+        /// </summary>
119
+        /// <param name="predicate">The predicate</param>
120
+        /// <returns>The object that match, or null</returns>
121
+        public static OpResult<TDbObject> GetSingle(Expression<Func<TDbObject, bool>> predicate)
122
+        {
123
+            return Execute((db, table) =>
124
+            {
125
+                var o = table.FirstOrDefault(predicate);
126
+                if (o == null)
127
+                {
128
+                    return OpResult<TDbObject>.Error(ResultStatus.NotFound, typeof(TThis).Name + ": Value not found", "");
129
+                }
130
+                return OpResult<TDbObject>.Ok(o);
131
+
132
+            });
133
+        }
134
+
135
+        /// <summary>
136
+        /// Get a single DBO matching the predicate
137
+        /// </summary>
138
+        /// <param name="predicate">The predicate</param>
139
+        /// <returns>The object that match, or null</returns>
140
+        public static OpResult<TDbo> GetSingleDbo(Expression<Func<TDbObject, bool>> predicate)
141
+        {
142
+            return DbToDboStatic(GetSingle(predicate));
143
+        }
144
+
145
+        /// <summary>
146
+        /// Get all DB object matching the predicate
147
+        /// </summary>
148
+        /// <param name="predicate">The predicate</param>
149
+        /// <returns>All matching objects</returns>
150
+        public static OpResult<IEnumerable<TDbObject>> GetMultiple(Expression<Func<TDbObject, bool>> predicate)
151
+        {
152
+            return Execute((db, table) => OpResult<IEnumerable<TDbObject>>.Ok(table.Where(predicate).ToList()));
153
+        }
154
+
155
+        /// <summary>
156
+        /// Get all DBO matching the predicate
157
+        /// </summary>
158
+        /// <typeparam name="TDbo">The DBO type</typeparam>
159
+        /// <param name="predicate">The predicate</param>
160
+        /// <returns>All matching objects</returns>
161
+        public static OpResult<IEnumerable<TDbo>> GetMultipleDbo(Expression<Func<TDbObject, bool>> predicate)
162
+        {
163
+            var res = GetMultiple(predicate);
164
+            if (!res)
165
+                return OpResult<IEnumerable<TDbo>>.Error(res);
166
+            var dbo = res.Data.Select(DbToDboStatic);
167
+            return OpResult<IEnumerable<TDbo>>.Ok(dbo);
168
+        }
169
+
170
+        /// <summary>
171
+        /// Add an entry in the database
172
+        /// </summary>
173
+        /// <param name="obj">The object to be added</param>
174
+        /// <returns>Always true or an OpResult error</returns>
175
+        public static OpResult<bool> Add(TDbObject obj)
176
+        {
177
+            return Execute((db, table) =>
178
+            {
179
+                table.Add(obj);
180
+                db.SaveChanges();
181
+                return OpResult<bool>.Ok(true);
182
+            });
183
+        }
184
+
185
+        /// <summary>
186
+        /// Add an entry in the database
187
+        /// </summary>
188
+        /// <param name="obj"></param>
189
+        /// <returns>Always true or an OpResult error</returns>
190
+        public static OpResult<bool> AddDbo(TDbo obj)
191
+        {
192
+            return Add(DboToDbStatic(obj));
193
+        }
194
+
195
+        /// <summary>
196
+        /// Get an object by its id
197
+        /// </summary>
198
+        /// <param name="id">The id of the object</param>
199
+        /// <returns>The object</returns>
200
+        public static OpResult<TDbObject> GetById(long id)
201
+        {
202
+            var param = Expression.Parameter(typeof(TDbObject), "x");
203
+            var exp = Expression.Lambda<Func<TDbObject, bool>>(
204
+                Expression.Equal(
205
+                    Expression.Property(param, "id"),
206
+                    Expression.Constant(id)
207
+                ), param);
208
+            return GetSingle(exp);
209
+        }
210
+
211
+        /// <summary>
212
+        /// Get an object by its id
213
+        /// </summary>
214
+        /// <param name="id">The id of the object</param>
215
+        /// <returns>The object</returns>
216
+        public static OpResult<TDbo> GetByIdDbo(long id)
217
+        {
218
+            return DbToDboStatic(GetById(id));
219
+        }
220
+    }
221
+}

+ 2279
- 0
WebApiUtils/Dynamic Expressions.html
File diff suppressed because it is too large
Näytä tiedosto


+ 17
- 0
WebApiUtils/WebApiUtils.csproj Näytä tiedosto

@@ -30,6 +30,18 @@
30 30
     <WarningLevel>4</WarningLevel>
31 31
   </PropertyGroup>
32 32
   <ItemGroup>
33
+    <Reference Include="Dynamic, Version=1.0.0.0, Culture=neutral, PublicKeyToken=68293a411f0cabcc, processorArchitecture=MSIL">
34
+      <HintPath>..\packages\DynamicQuery.1.0\lib\35\Dynamic.dll</HintPath>
35
+      <Private>True</Private>
36
+    </Reference>
37
+    <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
38
+      <HintPath>..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll</HintPath>
39
+      <Private>True</Private>
40
+    </Reference>
41
+    <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
42
+      <HintPath>..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll</HintPath>
43
+      <Private>True</Private>
44
+    </Reference>
33 45
     <Reference Include="Logs, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
34 46
       <HintPath>..\packages\Logs.dll.1.2.1\lib\net45\Logs.dll</HintPath>
35 47
       <Private>True</Private>
@@ -55,6 +67,7 @@
55 67
       <Private>True</Private>
56 68
     </Reference>
57 69
     <Reference Include="System" />
70
+    <Reference Include="System.ComponentModel.DataAnnotations" />
58 71
     <Reference Include="System.Core" />
59 72
     <Reference Include="System.Net.Http" />
60 73
     <Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@@ -79,6 +92,7 @@
79 92
     <Compile Include="BusinessManager\BMRHandler.cs" />
80 93
     <Compile Include="BusinessManager\CheckModelForNullAttribute.cs" />
81 94
     <Compile Include="BusinessManager\ExceptionLoggerAttribute.cs" />
95
+    <Compile Include="BusinessManager\SqlServerManager.cs" />
82 96
     <Compile Include="BusinessManager\ValidateModelStateAttribute.cs" />
83 97
     <Compile Include="BusinessManager\WebApiUtils.cs" />
84 98
     <Compile Include="Properties\AssemblyInfo.cs" />
@@ -87,6 +101,9 @@
87 101
     <None Include="app.config" />
88 102
     <None Include="packages.config" />
89 103
   </ItemGroup>
104
+  <ItemGroup>
105
+    <Content Include="Dynamic Expressions.html" />
106
+  </ItemGroup>
90 107
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
91 108
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
92 109
        Other similar extension points exist, see Microsoft.Common.targets.

+ 14
- 0
WebApiUtils/app.config Näytä tiedosto

@@ -1,5 +1,9 @@
1 1
 <?xml version="1.0" encoding="utf-8"?>
2 2
 <configuration>
3
+  <configSections>
4
+    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
5
+    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
6
+  </configSections>
3 7
   <runtime>
4 8
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
5 9
       <dependentAssembly>
@@ -8,4 +12,14 @@
8 12
       </dependentAssembly>
9 13
     </assemblyBinding>
10 14
   </runtime>
15
+  <entityFramework>
16
+    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
17
+      <parameters>
18
+        <parameter value="v11.0" />
19
+      </parameters>
20
+    </defaultConnectionFactory>
21
+    <providers>
22
+      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
23
+    </providers>
24
+  </entityFramework>
11 25
 </configuration>

+ 2
- 0
WebApiUtils/packages.config Näytä tiedosto

@@ -1,9 +1,11 @@
1 1
 <?xml version="1.0" encoding="utf-8"?>
2 2
 <packages>
3
+  <package id="DynamicQuery" version="1.0" targetFramework="net45" />
3 4
   <package id="EnterpriseLibrary.Common" version="6.0.1304.0" targetFramework="net45" />
4 5
   <package id="EnterpriseLibrary.Data" version="6.0.1304.0" targetFramework="net45" />
5 6
   <package id="EnterpriseLibrary.Logging" version="6.0.1304.0" targetFramework="net45" />
6 7
   <package id="EnterpriseLibrary.Logging.Database" version="6.0.1304.0" targetFramework="net45" />
8
+  <package id="EntityFramework" version="6.1.3" targetFramework="net45" />
7 9
   <package id="Logs.dll" version="1.2.1" targetFramework="net45" />
8 10
   <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net45" />
9 11
   <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" />

Loading…
Peruuta
Tallenna