From d8b0c51f899e4ed5d4aa9e42563d17d207a2e71a Mon Sep 17 00:00:00 2001 From: Michael Sawczyn Date: Thu, 15 Oct 2020 09:25:22 -0400 Subject: [PATCH] Fix UseTabs v2.0.5.7 --- src/Dsl/CustomCode/Partials/ModelRoot.cs | 6 +- src/Dsl/DslDefinition.dsl | 8 + src/Dsl/DslDefinition.dsl.diagram | 94 +- src/Dsl/GeneratedCode/DomainClasses.cs | 88 ++ src/Dsl/GeneratedCode/DomainModel.cs | 1 + src/Dsl/GeneratedCode/DomainModelResx.resx | 12 + src/Dsl/GeneratedCode/EFModelSchema.xsd | 6 + src/Dsl/GeneratedCode/LanguageNameSchema.xsd | 6 + src/Dsl/GeneratedCode/Serializer.cs | 30 + src/DslPackage/CustomCode/OptionsPage.cs | 61 +- .../CustomCode/Partials/EFModelDocData.cs | 1 - src/DslPackage/Parsers/EF6Parser.exe | Bin 9174948 -> 9174948 bytes src/DslPackage/Parsers/EFCore2Parser.exe | Bin 6243176 -> 6243176 bytes src/DslPackage/Parsers/EFCore3Parser.exe | Bin 8179210 -> 8179210 bytes .../ProjectItemTemplates/EFModel.xsd | 6 + .../TextTemplates/EFDesigner.ttinclude | 2 +- .../EditingOnly/EF6Designer.ttinclude | 802 ------------- .../EditingOnly/EFCoreDesigner.ttinclude | 705 ----------- .../TextTemplates/EditingOnly/EFDesigner.cs | 2 +- .../EditingOnly/EFDesigner.ttinclude | 1041 ----------------- src/Testing/Sandbox/Sandbox_EF6/EFModel1.cs | 2 +- .../Sandbox/Sandbox_EF6/EFModel1.efmodel | 2 +- .../Generated/Context/Context2.generated.cs | 196 ++-- .../Context2DatabaseInitializer.generated.cs | 8 +- ...text2DbMigrationConfiguration.generated.cs | 24 +- .../Generated/Context/Placeholder.txt | 1 - .../Generated/Entities/Base.generated.cs | 40 +- .../Generated/Entities/Entity1.generated.cs | 54 +- .../Generated/Entities/Entity2.generated.cs | 56 +- .../Generated/Entities/Entity3.generated.cs | 86 +- .../Generated/Entities/Placeholder.txt | 1 - .../Sandbox/Sandbox_EF6/Sandbox_EF6.csproj | 2 - 32 files changed, 495 insertions(+), 2848 deletions(-) delete mode 100644 src/DslPackage/TextTemplates/EditingOnly/EF6Designer.ttinclude delete mode 100644 src/DslPackage/TextTemplates/EditingOnly/EFCoreDesigner.ttinclude delete mode 100644 src/DslPackage/TextTemplates/EditingOnly/EFDesigner.ttinclude delete mode 100644 src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Placeholder.txt delete mode 100644 src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Placeholder.txt diff --git a/src/Dsl/CustomCode/Partials/ModelRoot.cs b/src/Dsl/CustomCode/Partials/ModelRoot.cs index 1641147c7..081df7a33 100644 --- a/src/Dsl/CustomCode/Partials/ModelRoot.cs +++ b/src/Dsl/CustomCode/Partials/ModelRoot.cs @@ -23,11 +23,9 @@ public partial class ModelRoot: IHasStore public static Action ExecuteValidator { get; set; } - public static Func GetCurrentDiagram; + public static Func GetCurrentDiagram { get; set; } - public static Func WriteDiagramAsBinary = () => false; - - public static Func UseTabs = () => false; + public static Func WriteDiagramAsBinary { get; set; } = () => false; static ModelRoot() { diff --git a/src/Dsl/DslDefinition.dsl b/src/Dsl/DslDefinition.dsl index 0cb306586..f5a3df5d0 100644 --- a/src/Dsl/DslDefinition.dsl +++ b/src/Dsl/DslDefinition.dsl @@ -305,6 +305,11 @@ + + + + + @@ -1993,6 +1998,9 @@ + + + diff --git a/src/Dsl/DslDefinition.dsl.diagram b/src/Dsl/DslDefinition.dsl.diagram index 98aa98a74..83209b4ab 100644 --- a/src/Dsl/DslDefinition.dsl.diagram +++ b/src/Dsl/DslDefinition.dsl.diagram @@ -4,18 +4,18 @@ - + - + - + @@ -39,11 +39,11 @@ - + - + @@ -95,16 +95,16 @@ - + - + - + - + @@ -113,10 +113,10 @@ - + - + @@ -125,16 +125,16 @@ - + - + - + - + @@ -170,10 +170,10 @@ - + - + @@ -182,22 +182,22 @@ - + - + - + - + - + - + @@ -230,34 +230,34 @@ - + - + - + - + - + - + - + - + - + - + @@ -333,20 +333,20 @@ - + - + - + @@ -381,13 +381,13 @@ - + - + @@ -412,13 +412,13 @@ - + - + @@ -478,14 +478,14 @@ - + - + @@ -506,7 +506,7 @@ - + @@ -519,13 +519,13 @@ - + - + @@ -565,7 +565,7 @@ - + @@ -585,7 +585,7 @@ - + diff --git a/src/Dsl/GeneratedCode/DomainClasses.cs b/src/Dsl/GeneratedCode/DomainClasses.cs index 6dc339c8c..59cf8ec25 100644 --- a/src/Dsl/GeneratedCode/DomainClasses.cs +++ b/src/Dsl/GeneratedCode/DomainClasses.cs @@ -3711,6 +3711,94 @@ public override sealed void SetValue(ModelRoot element, global::System.Boolean n } } + #endregion + #region UseTabs domain property code + + /// + /// UseTabs domain property Id. + /// + public static readonly global::System.Guid UseTabsDomainPropertyId = new global::System.Guid(0xc37804d1, 0x29d0, 0x4390, 0xa5, 0x2d, 0x9a, 0x9d, 0x3d, 0xd7, 0x94, 0x36); + + /// + /// Storage for UseTabs + /// + private global::System.Boolean useTabsPropertyStorage; + + /// + /// Gets or sets the value of UseTabs domain property. + /// If true, will generate code with tabs instead of spaces for indentation + /// + [DslDesign::DisplayNameResource("Sawczyn.EFDesigner.EFModel.ModelRoot/UseTabs.DisplayName", typeof(global::Sawczyn.EFDesigner.EFModel.EFModelDomainModel), "Sawczyn.EFDesigner.EFModel.GeneratedCode.DomainModelResx")] + [DslDesign::CategoryResource("Sawczyn.EFDesigner.EFModel.ModelRoot/UseTabs.Category", typeof(global::Sawczyn.EFDesigner.EFModel.EFModelDomainModel), "Sawczyn.EFDesigner.EFModel.GeneratedCode.DomainModelResx")] + [DslDesign::DescriptionResource("Sawczyn.EFDesigner.EFModel.ModelRoot/UseTabs.Description", typeof(global::Sawczyn.EFDesigner.EFModel.EFModelDomainModel), "Sawczyn.EFDesigner.EFModel.GeneratedCode.DomainModelResx")] + [DslModeling::DomainObjectId("c37804d1-29d0-4390-a52d-9a9d3dd79436")] + public global::System.Boolean UseTabs + { + [global::System.Diagnostics.DebuggerStepThrough] + get + { + return useTabsPropertyStorage; + } + [global::System.Diagnostics.DebuggerStepThrough] + set + { + UseTabsPropertyHandler.Instance.SetValue(this, value); + } + } + /// + /// Value handler for the ModelRoot.UseTabs domain property. + /// + internal sealed partial class UseTabsPropertyHandler : DslModeling::DomainPropertyValueHandler + { + private UseTabsPropertyHandler() { } + + /// + /// Gets the singleton instance of the ModelRoot.UseTabs domain property value handler. + /// + public static readonly UseTabsPropertyHandler Instance = new UseTabsPropertyHandler(); + + /// + /// Gets the Id of the ModelRoot.UseTabs domain property. + /// + public sealed override global::System.Guid DomainPropertyId + { + [global::System.Diagnostics.DebuggerStepThrough] + get + { + return UseTabsDomainPropertyId; + } + } + + /// + /// Gets a strongly-typed value of the property on specified element. + /// + /// Element which owns the property. + /// Property value. + public override sealed global::System.Boolean GetValue(ModelRoot element) + { + if (element == null) throw new global::System.ArgumentNullException("element"); + return element.useTabsPropertyStorage; + } + + /// + /// Sets property value on an element. + /// + /// Element which owns the property. + /// New property value. + public override sealed void SetValue(ModelRoot element, global::System.Boolean newValue) + { + if (element == null) throw new global::System.ArgumentNullException("element"); + + global::System.Boolean oldValue = GetValue(element); + if (newValue != oldValue) + { + ValueChanging(element, oldValue, newValue); + element.useTabsPropertyStorage = newValue; + ValueChanged(element, oldValue, newValue); + } + } + } + #endregion #region Comments opposite domain role accessor diff --git a/src/Dsl/GeneratedCode/DomainModel.cs b/src/Dsl/GeneratedCode/DomainModel.cs index 5a035b74b..3c80842d7 100644 --- a/src/Dsl/GeneratedCode/DomainModel.cs +++ b/src/Dsl/GeneratedCode/DomainModel.cs @@ -157,6 +157,7 @@ protected sealed override DomainMemberInfo[] GetGeneratedDomainProperties() new DomainMemberInfo(typeof(ModelRoot), "SnapToGrid", ModelRoot.SnapToGridDomainPropertyId, typeof(ModelRoot.SnapToGridPropertyHandler)), new DomainMemberInfo(typeof(ModelRoot), "GridColor", ModelRoot.GridColorDomainPropertyId, typeof(ModelRoot.GridColorPropertyHandler)), new DomainMemberInfo(typeof(ModelRoot), "ShowForeignKeyPropertyNames", ModelRoot.ShowForeignKeyPropertyNamesDomainPropertyId, typeof(ModelRoot.ShowForeignKeyPropertyNamesPropertyHandler)), + new DomainMemberInfo(typeof(ModelRoot), "UseTabs", ModelRoot.UseTabsDomainPropertyId, typeof(ModelRoot.UseTabsPropertyHandler)), new DomainMemberInfo(typeof(ModelClass), "IsAbstract", ModelClass.IsAbstractDomainPropertyId, typeof(ModelClass.IsAbstractPropertyHandler)), new DomainMemberInfo(typeof(ModelClass), "TableName", ModelClass.TableNameDomainPropertyId, typeof(ModelClass.TableNamePropertyHandler)), new DomainMemberInfo(typeof(ModelClass), "DatabaseSchema", ModelClass.DatabaseSchemaDomainPropertyId, typeof(ModelClass.DatabaseSchemaPropertyHandler)), diff --git a/src/Dsl/GeneratedCode/DomainModelResx.resx b/src/Dsl/GeneratedCode/DomainModelResx.resx index fc7383031..f9cca1a5b 100644 --- a/src/Dsl/GeneratedCode/DomainModelResx.resx +++ b/src/Dsl/GeneratedCode/DomainModelResx.resx @@ -621,6 +621,18 @@ Designer Category for DomainProperty 'ShowForeignKeyPropertyNames' on DomainClass 'ModelRoot' + + If true, will generate code with tabs instead of spaces for indentation + Description for DomainProperty 'UseTabs' on DomainClass 'ModelRoot' + + + Use Tabs + DisplayName for DomainProperty 'UseTabs' on DomainClass 'ModelRoot' + + + Code Generation + Category for DomainProperty 'UseTabs' on DomainClass 'ModelRoot' + Description for DomainClass 'ModelClass' diff --git a/src/Dsl/GeneratedCode/EFModelSchema.xsd b/src/Dsl/GeneratedCode/EFModelSchema.xsd index d4ebb81f9..344c7c1ea 100644 --- a/src/Dsl/GeneratedCode/EFModelSchema.xsd +++ b/src/Dsl/GeneratedCode/EFModelSchema.xsd @@ -321,6 +321,12 @@ If true, will show declared foreign key property names (if any) on the association ends + + + + If true, will generate code with tabs instead of spaces for indentation + + diff --git a/src/Dsl/GeneratedCode/LanguageNameSchema.xsd b/src/Dsl/GeneratedCode/LanguageNameSchema.xsd index d4ebb81f9..344c7c1ea 100644 --- a/src/Dsl/GeneratedCode/LanguageNameSchema.xsd +++ b/src/Dsl/GeneratedCode/LanguageNameSchema.xsd @@ -321,6 +321,12 @@ If true, will show declared foreign key property names (if any) on the association ends + + + + If true, will generate code with tabs instead of spaces for indentation + + diff --git a/src/Dsl/GeneratedCode/Serializer.cs b/src/Dsl/GeneratedCode/Serializer.cs index 255415c3b..39955ab64 100644 --- a/src/Dsl/GeneratedCode/Serializer.cs +++ b/src/Dsl/GeneratedCode/Serializer.cs @@ -817,6 +817,23 @@ protected override void ReadPropertiesFromAttributes(DslModeling::SerializationC } } } + // UseTabs + if (!serializationContext.Result.Failed) + { + string attribUseTabs = EFModelSerializationHelper.Instance.ReadAttribute(serializationContext, element, reader, "useTabs"); + if (attribUseTabs != null) + { + global::System.Boolean valueOfUseTabs; + if (DslModeling::SerializationUtilities.TryGetValue(serializationContext, attribUseTabs, out valueOfUseTabs)) + { + instanceOfModelRoot.UseTabs = valueOfUseTabs; + } + else + { // Invalid property value, ignored. + EFModelSerializationBehaviorSerializationMessages.IgnoredPropertyValue(serializationContext, reader, "useTabs", typeof(global::System.Boolean), attribUseTabs); + } + } + } } /// @@ -1973,6 +1990,19 @@ protected override void WritePropertiesAsAttributes(DslModeling::SerializationCo } } } + // UseTabs + if (!serializationContext.Result.Failed) + { + global::System.Boolean propValue = instanceOfModelRoot.UseTabs; + string serializedPropValue = DslModeling::SerializationUtilities.GetString(serializationContext, propValue); + if (!serializationContext.Result.Failed) + { + if (serializationContext.WriteOptionalPropertiesWithDefaultValue || string.CompareOrdinal(serializedPropValue, "false") != 0) + { // No need to write the value out if it's the same as default value. + EFModelSerializationHelper.Instance.WriteAttributeString(serializationContext, element, writer, "useTabs", serializedPropValue); + } + } + } } /// diff --git a/src/DslPackage/CustomCode/OptionsPage.cs b/src/DslPackage/CustomCode/OptionsPage.cs index 5831e2830..3805e748a 100644 --- a/src/DslPackage/CustomCode/OptionsPage.cs +++ b/src/DslPackage/CustomCode/OptionsPage.cs @@ -1,4 +1,5 @@ -using System.ComponentModel; +using System; +using System.ComponentModel; using System.Drawing.Design; using System.Windows.Forms.Design; @@ -6,22 +7,66 @@ namespace Sawczyn.EFDesigner.EFModel.DslPackage { + public class OptionsEventArgs : EventArgs + { + public string Option { get; } + public object OldValue { get; } + public object NewValue { get; } + + public OptionsEventArgs(string option, object oldValue, object newValue) + { + Option = option; + OldValue = oldValue; + NewValue = newValue; + } + } + public class OptionsPage : DialogPage { + public event EventHandler OptionChanged ; + + protected virtual void OnOptionsChanged(OptionsEventArgs args) + { + OptionChanged?.Invoke(this, args); + } + + private string dotExePath; + [Category("Display")] [DisplayName("GraphViz dot.exe path")] [Description("Path to the GraphViz dot.exe file, if present")] [Editor(typeof(FileNameEditor), typeof(UITypeEditor))] - public string DotExePath { get; set; } + public string DotExePath + { + get + { + return dotExePath; + } + set + { + OptionsEventArgs args = new OptionsEventArgs("DotExePath", dotExePath, value); + dotExePath = value; + OnOptionsChanged(args); + } + } + + private bool saveDiagramsCompressed; [Category("File")] [DisplayName("Save diagram using legacy binary format")] [Description("If true, .diagramx files will be saved in compressed format. If false, they will not.")] - public bool SaveDiagramsCompressed { get; set; } - - [Category("Code Generation")] - [DisplayName("Indent with tabs instead of spaces")] - [Description("If true, code will be generated using tabs and obey the editor's tab width")] - public bool UseTabs { get; set; } + public bool SaveDiagramsCompressed + { + get + { + return saveDiagramsCompressed; + } + set + { + OptionsEventArgs args = new OptionsEventArgs("SaveDiagramsCompressed", saveDiagramsCompressed, value); + saveDiagramsCompressed = value; + OnOptionsChanged(args); + } + } } } \ No newline at end of file diff --git a/src/DslPackage/CustomCode/Partials/EFModelDocData.cs b/src/DslPackage/CustomCode/Partials/EFModelDocData.cs index 8c3a9c413..4bada9350 100644 --- a/src/DslPackage/CustomCode/Partials/EFModelDocData.cs +++ b/src/DslPackage/CustomCode/Partials/EFModelDocData.cs @@ -215,7 +215,6 @@ protected override void OnDocumentLoaded() ModelRoot.ExecuteValidator = ValidateAll; ModelRoot.GetCurrentDiagram = GetCurrentDiagram; ModelRoot.WriteDiagramAsBinary = () => EFModelPackage.Options.SaveDiagramsCompressed; - ModelRoot.UseTabs = () => EFModelPackage.Options.UseTabs; ModelDiagramData.OpenDiagram = DisplayDiagram; ModelDiagramData.CloseDiagram = CloseDiagram; ModelDiagramData.RenameWindow = RenameWindow; diff --git a/src/DslPackage/Parsers/EF6Parser.exe b/src/DslPackage/Parsers/EF6Parser.exe index bf18cee7128b172767fcdbc71db805508ca622b0..3ced4e051705a5c62905f34d1f5a18b2a7a85cc9 100644 GIT binary patch delta 308 zcmWN=+cFdY007XjRFXtel!{73wxvadqUfdwMJ2jea@p7-msKJM;WO;}zL@FDdfS;e zGbiysnUOfSB27TL42K+cM5d#%9Fy(194F+;b5g!j3Y>OEp(1CUQ|!D8E-F##lFP0r zb5*$t*Ho%*Sf#{VW$JO2Xvm)3mL delta 308 zcmWN=X)_c6007WwZMilPBBc@%WgRV&il`KYE*&bZbBm>{YSBTx9QhgT_x;jLzsxr? z^k!aaFC9$%zv_U13_%ASk||5J9JxXc%X37&0!I}pQtX%#rH(6e!b#;$Iqi%JXH}|F z?VK9t)v9yBMfJiOG-}f9l86?q+FaJ|iVjy@b6uw{H+1W9(=E64y5p`s{qDJMz@Q-y zJoLz8PYiqNnde>@@zN`=jd~+$%(w}Yrc8@@>zx_1;^xeI?}G&ii$40~v!o@(0Fg ak6&p)B$G{MUlUKy@t4fo_h*p)3I72nqEJ-; delta 220 zcmWN=XD)*Q007V^HH+GN)SjjG`l!A4p8Y8rLAZb)FMd0W#8n)jmyqz1m-+Y&W&Xd* z5|S-PSgt(z3KS|5QLIF%s50d$RH{;~My)#a8Z>IstVOGsHtjle>e8)8uRi?-42l~v zEMdf`G2^{sSr7P=x>h diff --git a/src/DslPackage/Parsers/EFCore3Parser.exe b/src/DslPackage/Parsers/EFCore3Parser.exe index e6563e04a5de769d4e8fdfa02f8c92db6a910e1c..53de068d53a9f3134e8e6c45e87c3d8fd8b9d6e7 100644 GIT binary patch delta 278 zcmWN=MN$<2007XTq(K^KX{C`6>FyLsr8_k)lM45i3r-j}jzGk}O54H0eIckSR;H9J%s*majmeBE?FS`r@lH z9kxCxV{{50*C8MEfh zTd?T2Kb9<8v1-k_4V$)X+p%lUz5|B>j{Nn{u@nEDI&<#Ar7PDDH_uNo7j=QH)0*8t O!@Ws8y$4gGNo>Xx8GbR&CmKc&AgBZav=npjV%M9}O5ZWY~yNpM3Vkm~j)n`exFU zX)|Wc`R<3G<}FyXWZ5sjtyr~Y-5-B#2->t|+m2m(Lc;bPICSLLiBl10&Rw{?j^4)7 V_Cn#E@M@&BDHx30+{L1SIf true, will show declared foreign key property names (if any) on the association ends + + + + If true, will generate code with tabs instead of spaces for indentation + + diff --git a/src/DslPackage/TextTemplates/EFDesigner.ttinclude b/src/DslPackage/TextTemplates/EFDesigner.ttinclude index 39384e713..e4b289990 100644 --- a/src/DslPackage/TextTemplates/EFDesigner.ttinclude +++ b/src/DslPackage/TextTemplates/EFDesigner.ttinclude @@ -281,7 +281,7 @@ WriteLine(text); if (text.EndsWith("{")) - PushIndent(ModelRoot.UseTabs() ? "\t" : " "); + PushIndent(ModelRoot.UseTabs ? "\t" : " "); } void Output(string template, params object[] items) diff --git a/src/DslPackage/TextTemplates/EditingOnly/EF6Designer.ttinclude b/src/DslPackage/TextTemplates/EditingOnly/EF6Designer.ttinclude deleted file mode 100644 index 0c49d06a5..000000000 --- a/src/DslPackage/TextTemplates/EditingOnly/EF6Designer.ttinclude +++ /dev/null @@ -1,802 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data.Entity.Design.PluralizationServices; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Linq; -// ReSharper disable RedundantNameQualifier - -namespace System.Data.Entity.Design.PluralizationServices -{ - internal class PluralizationService - { - internal bool IsSingular(string _) { return true; } - - internal string Pluralize(string _) { return string.Empty; } - } -} - -namespace Sawczyn.EFDesigner.EFModel.DslPackage.TextTemplates.EditingOnly -{ - [SuppressMessage("ReSharper", "UnusedMember.Local")] - [SuppressMessage("ReSharper", "UnusedMember.Global")] - partial class EditOnly - { - // EFDesigner v2.0.5.7 - // Copyright (c) 2017-2020 Michael Sawczyn - // https://github.com/msawczyn/EFDesigner - - /************************************************** - * EF6-specific code generation methods - */ - - void GenerateEF6(Manager manager, ModelRoot modelRoot) - { - // Entities - string fileNameMarker = string.IsNullOrEmpty(modelRoot.FileNameMarker) ? string.Empty : $".{modelRoot.FileNameMarker}"; - - foreach (ModelClass modelClass in modelRoot.Classes.Where(e => e.GenerateCode)) - { - manager.StartNewFile(Path.Combine(modelClass.EffectiveOutputDirectory, $"{modelClass.Name}{fileNameMarker}.cs")); - WriteClass(modelClass); - } - - // Enums - - foreach (ModelEnum modelEnum in modelRoot.Enums.Where(e => e.GenerateCode)) - { - manager.StartNewFile(Path.Combine(modelEnum.EffectiveOutputDirectory, $"{modelEnum.Name}{fileNameMarker}.cs")); - WriteEnum(modelEnum); - } - - // Context - - if (modelRoot.DatabaseInitializerType != DatabaseInitializerKind.None) - { - manager.StartNewFile(Path.Combine(modelRoot.ContextOutputDirectory, $"{modelRoot.EntityContainerName}DatabaseInitializer{fileNameMarker}.cs")); - WriteDatabaseInitializerEF6(modelRoot); - } - - manager.StartNewFile(Path.Combine(modelRoot.ContextOutputDirectory, $"{modelRoot.EntityContainerName}DbMigrationConfiguration{fileNameMarker}.cs")); - WriteMigrationConfigurationEF6(modelRoot); - - manager.StartNewFile(Path.Combine(modelRoot.ContextOutputDirectory, $"{modelRoot.EntityContainerName}{fileNameMarker}.cs")); - WriteDbContextEF6(modelRoot); - } - - string[] SpatialTypesEF6 - { - get - { - return new[] - { - "Geography" - , "GeographyCollection" - , "GeographyLineString" - , "GeographyMultiLineString" - , "GeographyMultiPoint" - , "GeographyMultiPolygon" - , "GeographyPoint" - , "GeographyPolygon" - , "Geometry" - , "GeometryCollection" - , "GeometryLineString" - , "GeometryMultiLineString" - , "GeometryMultiPoint" - , "GeometryMultiPolygon" - , "GeometryPoint" - , "GeometryPolygon" - }; - } - } - - List GetAdditionalUsingStatementsEF6(ModelRoot modelRoot) - { - List result = new List(); - List attributeTypes = modelRoot.Classes.SelectMany(c => c.Attributes).Select(a => a.Type).Distinct().ToList(); - - if (attributeTypes.Intersect(modelRoot.SpatialTypes).Any()) - result.Add("using System.Data.Entity.Spatial;"); - - return result; - } - - void WriteDatabaseInitializerEF6(ModelRoot modelRoot) - { - Output("using System.Data.Entity;"); - NL(); - - BeginNamespace(modelRoot.Namespace); - - Output("/// "); - - Output(modelRoot.DatabaseInitializerType == DatabaseInitializerKind.MigrateDatabaseToLatestVersion - ? $"public partial class {modelRoot.EntityContainerName}DatabaseInitializer : MigrateDatabaseToLatestVersion<{modelRoot.Namespace}.{modelRoot.EntityContainerName}, {GetMigrationNamespace(modelRoot)}.{modelRoot.EntityContainerName}DbMigrationConfiguration>" - : $"public partial class {modelRoot.EntityContainerName}DatabaseInitializer : {modelRoot.DatabaseInitializerType}<{modelRoot.Namespace}.{modelRoot.EntityContainerName}>"); - - Output("{"); - Output("}"); - EndNamespace(modelRoot.Namespace); - } - - void WriteDbContextEF6(ModelRoot modelRoot) - { - ModelClass[] classesWithTables = null; - - switch (modelRoot.InheritanceStrategy) - { - case CodeStrategy.TablePerType: - classesWithTables = modelRoot.Classes.Where(mc => !mc.IsDependentType && mc.GenerateCode).OrderBy(x => x.Name).ToArray(); - - break; - - case CodeStrategy.TablePerConcreteType: - classesWithTables = modelRoot.Classes.Where(mc => !mc.IsDependentType && !mc.IsAbstract && mc.GenerateCode).OrderBy(x => x.Name).ToArray(); - - break; - - case CodeStrategy.TablePerHierarchy: - classesWithTables = modelRoot.Classes.Where(mc => !mc.IsDependentType && mc.Superclass == null && mc.GenerateCode).OrderBy(x => x.Name).ToArray(); - - break; - } - - Output("using System;"); - Output("using System.Collections.Generic;"); - Output("using System.Linq;"); - Output("using System.ComponentModel.DataAnnotations.Schema;"); - Output("using System.Data.Entity;"); - Output("using System.Data.Entity.Infrastructure.Annotations;"); - NL(); - - BeginNamespace(modelRoot.Namespace); - - WriteDbContextComments(modelRoot); - - string baseClass = string.IsNullOrWhiteSpace(modelRoot.BaseClass) ? "System.Data.Entity.DbContext" : modelRoot.BaseClass; - - Output($"{modelRoot.EntityContainerAccess.ToString().ToLower()} partial class {modelRoot.EntityContainerName} : {baseClass}"); - Output("{"); - - if (classesWithTables?.Any() == true) - WriteDbSetsEF6(modelRoot); - - WriteConstructorsEF6(modelRoot); - WriteModelCreateEF6(modelRoot, classesWithTables); - - Output("}"); - - EndNamespace(modelRoot.Namespace); - } - - private void WriteDbSetsEF6(ModelRoot modelRoot) - { - Output("#region DbSets"); - PluralizationService pluralizationService = ModelRoot.PluralizationService; - - foreach (ModelClass modelClass in modelRoot.Classes.Where(x => !x.IsDependentType).OrderBy(x => x.Name)) - { - string dbSetName; - - if (!string.IsNullOrEmpty(modelClass.DbSetName)) - dbSetName = modelClass.DbSetName; - else - { - dbSetName = pluralizationService?.IsSingular(modelClass.Name) == true - ? pluralizationService.Pluralize(modelClass.Name) - : modelClass.Name; - } - - if (!string.IsNullOrEmpty(modelClass.Summary)) - { - NL(); - Output("/// "); - WriteCommentBody($"Repository for {modelClass.FullName} - {modelClass.Summary}"); - Output("/// "); - } - - Output($"{modelRoot.DbSetAccess.ToString().ToLower()} virtual System.Data.Entity.DbSet<{modelClass.FullName}> {dbSetName} {{ get; set; }}"); - } - - Output("#endregion DbSets"); - NL(); - } - - private void WriteConstructorsEF6(ModelRoot modelRoot) - { - Output("#region Constructors"); - NL(); - Output("partial void CustomInit();"); - NL(); - - if (!string.IsNullOrEmpty(modelRoot.ConnectionString) || !string.IsNullOrEmpty(modelRoot.ConnectionStringName)) - { - string connectionString = string.IsNullOrEmpty(modelRoot.ConnectionString) - ? $"Name={modelRoot.ConnectionStringName}" - : modelRoot.ConnectionString; - - Output("/// "); - Output("/// Default connection string"); - Output("/// "); - Output($"public static string ConnectionString {{ get; set; }} = @\"{connectionString}\";"); - - Output("/// "); - Output($"public {modelRoot.EntityContainerName}() : base(ConnectionString)"); - Output("{"); - Output($"Configuration.LazyLoadingEnabled = {modelRoot.LazyLoadingEnabled.ToString().ToLower()};"); - Output($"Configuration.ProxyCreationEnabled = {modelRoot.ProxyGenerationEnabled.ToString().ToLower()};"); - - Output(modelRoot.DatabaseInitializerType == DatabaseInitializerKind.None - ? $"System.Data.Entity.Database.SetInitializer<{modelRoot.EntityContainerName}>(null);" - : $"System.Data.Entity.Database.SetInitializer<{modelRoot.EntityContainerName}>(new {modelRoot.EntityContainerName}DatabaseInitializer());"); - - Output("CustomInit();"); - Output("}"); - NL(); - } - else - { - Output($"#warning Default constructor not generated for {modelRoot.EntityContainerName} since no default connection string was specified in the model"); - NL(); - } - - Output("/// "); - Output($"public {modelRoot.EntityContainerName}(string connectionString) : base(connectionString)"); - Output("{"); - Output($"Configuration.LazyLoadingEnabled = {modelRoot.LazyLoadingEnabled.ToString().ToLower()};"); - Output($"Configuration.ProxyCreationEnabled = {modelRoot.ProxyGenerationEnabled.ToString().ToLower()};"); - - Output(modelRoot.DatabaseInitializerType == DatabaseInitializerKind.None - ? $"System.Data.Entity.Database.SetInitializer<{modelRoot.EntityContainerName}>(null);" - : $"System.Data.Entity.Database.SetInitializer<{modelRoot.EntityContainerName}>(new {modelRoot.EntityContainerName}DatabaseInitializer());"); - - Output("CustomInit();"); - Output("}"); - NL(); - - Output("/// "); - Output($"public {modelRoot.EntityContainerName}(string connectionString, System.Data.Entity.Infrastructure.DbCompiledModel model) : base(connectionString, model)"); - Output("{"); - Output($"Configuration.LazyLoadingEnabled = {modelRoot.LazyLoadingEnabled.ToString().ToLower()};"); - Output($"Configuration.ProxyCreationEnabled = {modelRoot.ProxyGenerationEnabled.ToString().ToLower()};"); - - Output(modelRoot.DatabaseInitializerType == DatabaseInitializerKind.None - ? $"System.Data.Entity.Database.SetInitializer<{modelRoot.EntityContainerName}>(null);" - : $"System.Data.Entity.Database.SetInitializer<{modelRoot.EntityContainerName}>(new {modelRoot.EntityContainerName}DatabaseInitializer());"); - - Output("CustomInit();"); - Output("}"); - NL(); - - Output("/// "); - Output($"public {modelRoot.EntityContainerName}(System.Data.Common.DbConnection existingConnection, bool contextOwnsConnection) : base(existingConnection, contextOwnsConnection)"); - Output("{"); - Output($"Configuration.LazyLoadingEnabled = {modelRoot.LazyLoadingEnabled.ToString().ToLower()};"); - Output($"Configuration.ProxyCreationEnabled = {modelRoot.ProxyGenerationEnabled.ToString().ToLower()};"); - - Output(modelRoot.DatabaseInitializerType == DatabaseInitializerKind.None - ? $"System.Data.Entity.Database.SetInitializer<{modelRoot.EntityContainerName}>(null);" - : $"System.Data.Entity.Database.SetInitializer<{modelRoot.EntityContainerName}>(new {modelRoot.EntityContainerName}DatabaseInitializer());"); - - Output("CustomInit();"); - Output("}"); - NL(); - - Output("/// "); - Output($"public {modelRoot.EntityContainerName}(System.Data.Common.DbConnection existingConnection, System.Data.Entity.Infrastructure.DbCompiledModel model, bool contextOwnsConnection) : base(existingConnection, model, contextOwnsConnection)"); - Output("{"); - Output($"Configuration.LazyLoadingEnabled = {modelRoot.LazyLoadingEnabled.ToString().ToLower()};"); - Output($"Configuration.ProxyCreationEnabled = {modelRoot.ProxyGenerationEnabled.ToString().ToLower()};"); - - Output(modelRoot.DatabaseInitializerType == DatabaseInitializerKind.None - ? $"System.Data.Entity.Database.SetInitializer<{modelRoot.EntityContainerName}>(null);" - : $"System.Data.Entity.Database.SetInitializer<{modelRoot.EntityContainerName}>(new {modelRoot.EntityContainerName}DatabaseInitializer());"); - - Output("CustomInit();"); - Output("}"); - NL(); - - Output("/// "); - Output($"public {modelRoot.EntityContainerName}(System.Data.Entity.Infrastructure.DbCompiledModel model) : base(model)"); - Output("{"); - Output($"Configuration.LazyLoadingEnabled = {modelRoot.LazyLoadingEnabled.ToString().ToLower()};"); - Output($"Configuration.ProxyCreationEnabled = {modelRoot.ProxyGenerationEnabled.ToString().ToLower()};"); - - Output(modelRoot.DatabaseInitializerType == DatabaseInitializerKind.None - ? $"System.Data.Entity.Database.SetInitializer<{modelRoot.EntityContainerName}>(null);" - : $"System.Data.Entity.Database.SetInitializer<{modelRoot.EntityContainerName}>(new {modelRoot.EntityContainerName}DatabaseInitializer());"); - - Output("CustomInit();"); - Output("}"); - NL(); - - Output("/// "); - Output($"public {modelRoot.EntityContainerName}(System.Data.Entity.Core.Objects.ObjectContext objectContext, bool dbContextOwnsObjectContext) : base(objectContext, dbContextOwnsObjectContext)"); - Output("{"); - Output($"Configuration.LazyLoadingEnabled = {modelRoot.LazyLoadingEnabled.ToString().ToLower()};"); - Output($"Configuration.ProxyCreationEnabled = {modelRoot.ProxyGenerationEnabled.ToString().ToLower()};"); - - Output(modelRoot.DatabaseInitializerType == DatabaseInitializerKind.None - ? $"System.Data.Entity.Database.SetInitializer<{modelRoot.EntityContainerName}>(null);" - : $"System.Data.Entity.Database.SetInitializer<{modelRoot.EntityContainerName}>(new {modelRoot.EntityContainerName}DatabaseInitializer());"); - - Output("CustomInit();"); - Output("}"); - NL(); - Output("#endregion Constructors"); - NL(); - } - - private void WriteModelCreateEF6(ModelRoot modelRoot, ModelClass[] classesWithTables) - { - Output("partial void OnModelCreatingImpl(System.Data.Entity.DbModelBuilder modelBuilder);"); - Output("partial void OnModelCreatedImpl(System.Data.Entity.DbModelBuilder modelBuilder);"); - NL(); - - Output("/// "); - Output("protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)"); - Output("{"); - Output("base.OnModelCreating(modelBuilder);"); - Output("OnModelCreatingImpl(modelBuilder);"); - NL(); - - if (!string.IsNullOrEmpty(modelRoot.DatabaseSchema)) - Output($"modelBuilder.HasDefaultSchema(\"{modelRoot.DatabaseSchema}\");"); - - List segments = new List(); - - List visited = new List(); - List foreignKeyColumns = new List(); - List declaredShadowProperties = new List(); - - foreach (ModelClass modelClass in modelRoot.Classes.OrderBy(x => x.Name)) - { - segments.Clear(); - foreignKeyColumns.Clear(); - declaredShadowProperties.Clear(); - NL(); - - // class level - bool isDependent = modelClass.IsDependentType; - segments.Add($"modelBuilder.{(isDependent ? "ComplexType" : "Entity")}<{modelClass.FullName}>()"); - - foreach (ModelAttribute transient in modelClass.Attributes.Where(x => !x.Persistent)) - segments.Add($"Ignore(t => t.{transient.Name})"); - - if (!isDependent) - { - // note: this must come before the 'ToTable' call or there's a runtime error - if (modelRoot.InheritanceStrategy == CodeStrategy.TablePerConcreteType && modelClass.Superclass != null) - segments.Add("Map(x => x.MapInheritedProperties())"); - - if (classesWithTables.Contains(modelClass)) - { - if (modelRoot.InheritanceStrategy != CodeStrategy.TablePerConcreteType || !modelClass.IsAbstract) - { - segments.Add(string.IsNullOrEmpty(modelClass.DatabaseSchema) || modelClass.DatabaseSchema == modelClass.ModelRoot.DatabaseSchema - ? $"ToTable(\"{modelClass.TableName}\")" - : $"ToTable(\"{modelClass.TableName}\", \"{modelClass.DatabaseSchema}\")"); - } - - // primary key code segments must be output last, since HasKey returns a different type - List identityAttributes = modelClass.AllIdentityAttributes.ToList(); - - if (identityAttributes.Count == 1) - segments.Add($"HasKey(t => t.{identityAttributes[0].Name})"); - else if (identityAttributes.Count > 1) - segments.Add($"HasKey(t => new {{ t.{string.Join(", t.", identityAttributes.Select(ia => ia.Name))} }})"); - } - } - - if (segments.Count > 1 || isDependent) - { - if (modelRoot.ChopMethodChains) - OutputChopped(segments); - else - Output(string.Join(".", segments) + ";"); - } - - if (isDependent) - continue; - - // attribute level - foreach (ModelAttribute modelAttribute in modelClass.Attributes.Where(x => x.Persistent && !SpatialTypesEF6.Contains(x.Type))) - { - segments.Clear(); - - if ((modelAttribute.MaxLength ?? 0) > 0) - segments.Add($"HasMaxLength({modelAttribute.MaxLength})"); - - if (modelAttribute.Required) - segments.Add("IsRequired()"); - - if (modelAttribute.ColumnName != modelAttribute.Name && !string.IsNullOrEmpty(modelAttribute.ColumnName)) - segments.Add($"HasColumnName(\"{modelAttribute.ColumnName}\")"); - - if (!string.IsNullOrEmpty(modelAttribute.ColumnType) && modelAttribute.ColumnType.ToLowerInvariant() != "default") - segments.Add($"HasColumnType(\"{modelAttribute.ColumnType}\")"); - - if (modelAttribute.Indexed && !modelAttribute.IsIdentity) - segments.Add("HasColumnAnnotation(\"Index\", new IndexAnnotation(new IndexAttribute()))"); - - if (modelAttribute.IsConcurrencyToken) - segments.Add("IsRowVersion()"); - - if (modelAttribute.IsIdentity) - { - segments.Add(modelAttribute.IdentityType == IdentityType.AutoGenerated - ? "HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)" - : "HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)"); - } - - if (segments.Any()) - { - segments.Insert(0, $"modelBuilder.{(isDependent ? "ComplexType" : "Entity")}<{modelClass.FullName}>()"); - segments.Insert(1, $"Property(t => t.{modelAttribute.Name})"); - - if (modelRoot.ChopMethodChains) - OutputChopped(segments); - else - Output(string.Join(".", segments) + ";"); - } - - if (modelAttribute.Indexed && !modelAttribute.IsIdentity) - { - segments.Clear(); - - segments.Add($"modelBuilder.Entity<{modelClass.FullName}>().HasIndex(t => t.{modelAttribute.Name})"); - - if (modelAttribute.IndexedUnique) - segments.Add("IsUnique()"); - - if (segments.Count > 1) - { - if (modelRoot.ChopMethodChains) - OutputChopped(segments); - else - Output(string.Join(".", segments) + ";"); - } - } - } - - if (!isDependent) - { - // Navigation endpoints are distingished as Source and Target. They are also distinguished as Principal - // and Dependent. How do these map? - // In the case of one-to-one or zero-to-one-to-zero-to-one, it's model dependent and the user has to tell us - // In all other cases, we can tell by the cardinalities of the associations - // What matters is the Principal and Dependent classifications, so we look at those. - // Source and Target are accidents of where the user started drawing the association. - - // navigation properties - - // ReSharper disable once LoopCanBePartlyConvertedToQuery - foreach (UnidirectionalAssociation association in Association.GetLinksToTargets(modelClass) - .OfType() - .Where(x => x.Persistent && !x.Target.IsDependentType)) - { - if (visited.Contains(association)) - continue; - - visited.Add(association); - - segments.Clear(); - segments.Add($"modelBuilder.Entity<{modelClass.FullName}>()"); - - switch (association.TargetMultiplicity) // realized by property on source - { - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany: - segments.Add($"HasMany(x => x.{association.TargetPropertyName})"); - - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.One: - segments.Add($"HasRequired(x => x.{association.TargetPropertyName})"); - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroOne: - segments.Add($"HasOptional(x => x.{association.TargetPropertyName})"); - - break; - - //case Sawczyn.EFDesigner.EFModel.Multiplicity.OneMany: - // segments.Add($"HasMany(x => x.{association.TargetPropertyName})"); - // break; - } - - switch (association.SourceMultiplicity) // realized by property on target, but no property on target - { - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany: - segments.Add("WithMany()"); - - if (association.TargetMultiplicity == Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany) - { - string tableMap = string.IsNullOrEmpty(association.JoinTableName) ? $"{association.Source.Name}_x_{association.TargetPropertyName}" : association.JoinTableName; - string suffix1 = association.Source == association.Target ? "A" : ""; - string suffix2 = association.Source == association.Target ? "B" : ""; - string sourceMap = string.Join(", ", association.Source.AllIdentityAttributeNames.Select(n => $@"""{association.Source.Name}_{n}{suffix1}""").ToList()); - string targetMap = string.Join(", ", association.Target.AllIdentityAttributeNames.Select(n => $@"""{association.Target.Name}_{n}{suffix2}""").ToList()); - - segments.Add(modelClass == association.Source - ? $@"Map(x => {{ x.ToTable(""{tableMap}""); x.MapLeftKey({sourceMap}); x.MapRightKey({targetMap}); }})" - : $@"Map(x => {{ x.ToTable(""{tableMap}""); x.MapLeftKey({targetMap}); x.MapRightKey({sourceMap}); }})"); - } - - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.One: - if (association.TargetMultiplicity == Sawczyn.EFDesigner.EFModel.Multiplicity.One) - { - segments.Add(association.TargetRole == EndpointRole.Dependent - ? "WithRequiredDependent()" - : "WithRequiredPrincipal()"); - } - else - segments.Add("WithRequired()"); - - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroOne: - if (association.TargetMultiplicity == Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroOne) - { - segments.Add(association.TargetRole == EndpointRole.Dependent - ? "WithOptionalDependent()" - : "WithOptionalPrincipal()"); - } - else - segments.Add("WithOptional()"); - - break; - - //case Sawczyn.EFDesigner.EFModel.Multiplicity.OneMany: - // segments.Add("HasMany()"); - // break; - } - - string foreignKeySegment = CreateForeignKeySegmentEF6(association, foreignKeyColumns); - - // can't include shadow properties twice - if (foreignKeySegment != null) - { - if (!foreignKeySegment.Contains("MapKey")) - segments.Add(foreignKeySegment); - else if (!declaredShadowProperties.Contains(foreignKeySegment)) - { - declaredShadowProperties.Add(foreignKeySegment); - segments.Add(foreignKeySegment); - } - } - - // Certain associations cascade delete automatically. Also, the user may ask for it. - // We only generate a cascade delete call if the user asks for it. - if ((association.TargetDeleteAction != DeleteAction.Default && association.TargetRole == EndpointRole.Principal) || (association.SourceDeleteAction != DeleteAction.Default && association.SourceRole == EndpointRole.Principal)) - { - string willCascadeOnDelete = association.TargetDeleteAction != DeleteAction.Default && association.TargetRole == EndpointRole.Principal - ? (association.TargetDeleteAction == DeleteAction.Cascade).ToString().ToLowerInvariant() - : (association.SourceDeleteAction == DeleteAction.Cascade).ToString().ToLowerInvariant(); - - segments.Add($"WillCascadeOnDelete({willCascadeOnDelete})"); - } - - if (modelRoot.ChopMethodChains) - OutputChopped(segments); - else - Output(string.Join(".", segments) + ";"); - } - - // ReSharper disable once LoopCanBePartlyConvertedToQuery - foreach (BidirectionalAssociation association in Association.GetLinksToSources(modelClass) - .OfType() - .Where(x => x.Persistent)) - { - if (visited.Contains(association)) - continue; - - visited.Add(association); - - segments.Clear(); - segments.Add($"modelBuilder.Entity<{modelClass.FullName}>()"); - - switch (association.SourceMultiplicity) // realized by property on target - { - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany: - segments.Add($"HasMany(x => x.{association.SourcePropertyName})"); - - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.One: - segments.Add($"HasRequired(x => x.{association.SourcePropertyName})"); - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroOne: - segments.Add($"HasOptional(x => x.{association.SourcePropertyName})"); - - break; - - //one or more constraint not supported in EF. - // TODO: make this possible ... later - //case Sawczyn.EFDesigner.EFModel.Multiplicity.OneMany: - // segments.Add($"HasMany(x => x.{association.SourcePropertyName})"); - // break; - } - - switch (association.TargetMultiplicity) // realized by property on source - { - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany: - segments.Add($"WithMany(x => x.{association.TargetPropertyName})"); - - if (association.SourceMultiplicity == Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany) - { - string tableMap = string.IsNullOrEmpty(association.JoinTableName) ? $"{association.SourcePropertyName}_x_{association.TargetPropertyName}" : association.JoinTableName; - string suffix1 = association.Source == association.Target ? "A" : ""; - string suffix2 = association.Source == association.Target ? "B" : ""; - string sourceMap = string.Join(", ", association.Source.AllIdentityAttributeNames.Select(n => $@"""{association.Source.Name}_{n}{suffix1}""").ToList()); - string targetMap = string.Join(", ", association.Target.AllIdentityAttributeNames.Select(n => $@"""{association.Target.Name}_{n}{suffix2}""").ToList()); - - segments.Add(modelClass == association.Source - ? $@"Map(x => {{ x.ToTable(""{tableMap}""); x.MapLeftKey({sourceMap}); x.MapRightKey({targetMap}); }})" - : $@"Map(x => {{ x.ToTable(""{tableMap}""); x.MapLeftKey({targetMap}); x.MapRightKey({sourceMap}); }})"); - } - - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.One: - if (association.SourceMultiplicity == Sawczyn.EFDesigner.EFModel.Multiplicity.One) - { - segments.Add(association.SourceRole == EndpointRole.Dependent - ? $"WithRequiredDependent(x => x.{association.TargetPropertyName})" - : $"WithRequiredPrincipal(x => x.{association.TargetPropertyName})"); - } - else - segments.Add($"WithRequired(x => x.{association.TargetPropertyName})"); - - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroOne: - if (association.SourceMultiplicity == Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroOne) - { - segments.Add(association.SourceRole == EndpointRole.Dependent - ? $"WithOptionalDependent(x => x.{association.TargetPropertyName})" - : $"WithOptionalPrincipal(x => x.{association.TargetPropertyName})"); - } - else - segments.Add($"WithOptional(x => x.{association.TargetPropertyName})"); - - break; - - //one or more constraint not supported in EF. TODO: make this possible ... later - //case Sawczyn.EFDesigner.EFModel.Multiplicity.OneMany: - // segments.Add($"HasMany(x => x.{association.TargetPropertyName})"); - // break; - } - - string foreignKeySegment = CreateForeignKeySegmentEF6(association, foreignKeyColumns); - - // can't shadow properties twice - if (foreignKeySegment != null) - { - if (!foreignKeySegment.Contains("MapKey")) - segments.Add(foreignKeySegment); - else if (!declaredShadowProperties.Contains(foreignKeySegment)) - { - declaredShadowProperties.Add(foreignKeySegment); - segments.Add(foreignKeySegment); - } - } - - if ((association.TargetDeleteAction != DeleteAction.Default && association.TargetRole == EndpointRole.Principal) || (association.SourceDeleteAction != DeleteAction.Default && association.SourceRole == EndpointRole.Principal)) - { - string willCascadeOnDelete = association.TargetDeleteAction != DeleteAction.Default && association.TargetRole == EndpointRole.Principal - ? (association.TargetDeleteAction == DeleteAction.Cascade).ToString().ToLowerInvariant() - : (association.SourceDeleteAction == DeleteAction.Cascade).ToString().ToLowerInvariant(); - - segments.Add($"WillCascadeOnDelete({willCascadeOnDelete})"); - } - - if (modelRoot.ChopMethodChains) - OutputChopped(segments); - else - Output(string.Join(".", segments) + ";"); - } - } - } - - NL(); - - Output("OnModelCreatedImpl(modelBuilder);"); - Output("}"); - } - - string GetMigrationNamespace(ModelRoot modelRoot) - { - List nsParts = modelRoot.Namespace.Split('.').ToList(); - nsParts = nsParts.Take(nsParts.Count - 1).ToList(); - nsParts.Add("Migrations"); - return string.Join(".", nsParts); - } - - void WriteMigrationConfigurationEF6(ModelRoot modelRoot) - { - Output("using System.Data.Entity.Migrations;"); - NL(); - - BeginNamespace(GetMigrationNamespace(modelRoot)); - Output("/// "); - Output($"public sealed partial class {modelRoot.EntityContainerName}DbMigrationConfiguration : DbMigrationsConfiguration<{modelRoot.Namespace}.{modelRoot.EntityContainerName}>"); - - Output("{"); - Output("partial void Init();"); - NL(); - - Output("/// "); - Output($"public {modelRoot.EntityContainerName}DbMigrationConfiguration()"); - Output("{"); - Output($"AutomaticMigrationsEnabled = {modelRoot.AutomaticMigrationsEnabled.ToString().ToLower()};"); - Output("AutomaticMigrationDataLossAllowed = false;"); - Output("Init();"); - Output("}"); - - Output("}"); - EndNamespace(modelRoot.Namespace); - } - - string CreateForeignKeySegmentEF6(Association association, List foreignKeyColumns) - { - // foreign key definitions always go in the table representing the Dependent end of the association - // if there is no dependent end (i.e., many-to-many), there are no foreign keys - ModelClass principal; - ModelClass dependent; - - // declaring foreign keys can only happen on ..n multiplicities - // otherwise, primary keys are required to be used, and the framework takes care of that - if (association.TargetMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany && association.SourceMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany) - return null; - - if (association.SourceRole == EndpointRole.Dependent) - { - dependent = association.Source; - principal = association.Target; - } - else if (association.TargetRole == EndpointRole.Dependent) - { - dependent = association.Target; - principal = association.Source; - } - else - return null; - - string columnNames; - - // shadow properties - if (string.IsNullOrWhiteSpace(association.FKPropertyName)) - { - columnNames = string.Join(", " - , principal.AllIdentityAttributes - .Select(a => $"\"{CreateShadowPropertyName(association, foreignKeyColumns, a)}\"")); - - string[] columnNameList = columnNames.Split(',').Select(n => n.Trim()).ToArray(); - string[] dependentPropertyNames = dependent.AllPropertyNames.ToArray(); - - int existingPropertyCount = columnNameList.Intersect(dependentPropertyNames).Count(); - - if (existingPropertyCount > 0) - { - return existingPropertyCount == 1 - ? $"HasForeignKey(p => {columnNames})" - : $"HasForeignKey(p => new {{ {string.Join(", ", columnNameList.Select(n => $"p.{n}"))} }}"; - } - else - return $"Map(x => x.MapKey({columnNames}))"; - } - - // defined properties - columnNames = association.FKPropertyName.Contains(",") - ? $"new {{ {string.Join(", ", association.FKPropertyName.Split(',').Select(n => $"p.{n.Trim()}"))} }}" - : $"p.{association.FKPropertyName.Trim()}"; - - return $"HasForeignKey(p => {columnNames})"; - } - } -} - - diff --git a/src/DslPackage/TextTemplates/EditingOnly/EFCoreDesigner.ttinclude b/src/DslPackage/TextTemplates/EditingOnly/EFCoreDesigner.ttinclude deleted file mode 100644 index 428b6c45d..000000000 --- a/src/DslPackage/TextTemplates/EditingOnly/EFCoreDesigner.ttinclude +++ /dev/null @@ -1,705 +0,0 @@ -using System.Collections.Generic; -using System.Data.Entity.Design.PluralizationServices; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Linq; -// ReSharper disable RedundantNameQualifier - -namespace Sawczyn.EFDesigner.EFModel.DslPackage.TextTemplates.EditingOnly -{ - [SuppressMessage("ReSharper", "UnusedMember.Local")] - [SuppressMessage("ReSharper", "UnusedMember.Global")] - partial class EditOnly - { - // EFDesigner v2.0.5.7 - // Copyright (c) 2017-2020 Michael Sawczyn - // https://github.com/msawczyn/EFDesigner - - /************************************************** - * EFCore-specific code generation methods - */ - - void GenerateEFCore(Manager manager, ModelRoot modelRoot) - { - // Entities - string fileNameMarker = string.IsNullOrEmpty(modelRoot.FileNameMarker) ? string.Empty : $".{modelRoot.FileNameMarker}"; - - foreach (ModelClass modelClass in modelRoot.Classes.Where(e => e.GenerateCode)) - { - manager.StartNewFile(Path.Combine(modelClass.EffectiveOutputDirectory, $"{modelClass.Name}{fileNameMarker}.cs")); - WriteClass(modelClass); - } - - // Enums - - foreach (ModelEnum modelEnum in modelRoot.Enums.Where(e => e.GenerateCode)) - { - manager.StartNewFile(Path.Combine(modelEnum.EffectiveOutputDirectory, $"{modelEnum.Name}{fileNameMarker}.cs")); - WriteEnum(modelEnum); - } - - // DatabaseInitializer not yet supported in EF Core - // manager.StartNewFile(Path.Combine(modelRoot.ContextOutputDirectory, $"{modelRoot.EntityContainerName}DatabaseInitializer{fileNameMarker}.cs")); - // WriteDatabaseInitializerEFCore(modelRoot); - - // MigrationConfiguration not yet supported in EF Core - // manager.StartNewFile(Path.Combine(modelRoot.ContextOutputDirectory, $"{modelRoot.EntityContainerName}DbMigrationConfiguration{fileNameMarker}.cs")); - // WriteMigrationConfigurationEFCore(modelRoot); - - manager.StartNewFile(Path.Combine(modelRoot.ContextOutputDirectory, $"{modelRoot.EntityContainerName}{fileNameMarker}.cs")); - WriteDbContextEFCore(modelRoot); - } - - string[] SpatialTypesEFCore - { - get - { - return new[] { - "Geometry" - , "GeometryPoint" - , "GeometryLineString" - , "GeometryPolygon" - , "GeometryCollection" - , "GeometryMultiPoint" - , "GeometryMultiLineString" - , "GeometryMultiPolygon" - }; - } - } - - List GetAdditionalUsingStatementsEFCore(ModelRoot modelRoot) - { - List result = new List(); - List attributeTypes = modelRoot.Classes.SelectMany(c => c.Attributes).Select(a => a.Type).Distinct().ToList(); - - if (attributeTypes.Intersect(modelRoot.SpatialTypes).Any()) - result.Add("using NetTopologySuite.Geometries;"); - - return result; - } - - // Revisit if/when supported in EFCore - - // void WriteDatabaseInitializerEFCore(ModelRoot modelRoot) - // { - // Output("using System.Data.Entity;"); - // NL(); - // - // BeginNamespace(modelRoot.Namespace); - // - // if (modelRoot.DatabaseInitializerType == DatabaseInitializerKind.MigrateDatabaseToLatestVersion) - // Output($"public partial class {modelRoot.EntityContainerName}DatabaseInitializer : MigrateDatabaseToLatestVersion<{modelRoot.EntityContainerName}, {modelRoot.EntityContainerName}DbMigrationConfiguration>"); - // else - // Output($"public partial class {modelRoot.EntityContainerName}DatabaseInitializer : {modelRoot.DatabaseInitializerType}<{modelRoot.EntityContainerName}>"); - // - // Output("{"); - // Output("}"); - // EndNamespace(modelRoot.Namespace); - // } - // - // void WriteMigrationConfigurationEFCore(ModelRoot modelRoot) - // { - // //if (modelRoot.DatabaseInitializerType != DatabaseInitializerKind.MigrateDatabaseToLatestVersion) - // // return; - // - // Output("using System.Data.Entity.Migrations;"); - // NL(); - // - // BeginNamespace(modelRoot.Namespace); - // Output("public sealed partial class {0}DbMigrationConfiguration : DbMigrationsConfiguration<{0}>", modelRoot.EntityContainerName); - // - // Output("{"); - // Output("partial void Init();"); - // NL(); - // - // Output("public {0}DbMigrationConfiguration()", modelRoot.EntityContainerName); - // Output("{"); - // Output("AutomaticMigrationsEnabled = {0};", modelRoot.AutomaticMigrationsEnabled.ToString().ToLower()); - // Output("AutomaticMigrationDataLossAllowed = false;"); - // Output("Init();"); - // Output("}"); - // - // Output("}"); - // EndNamespace(modelRoot.Namespace); - // } - - void WriteDbContextEFCore(ModelRoot modelRoot) - { - List segments = new List(); - ModelClass[] classesWithTables = null; - - // Note: TablePerType and TablePerConcreteType not yet available, but it doesn't hurt for them to be here since they shouldn't make it past the designer's validations - switch (modelRoot.InheritanceStrategy) - { - case CodeStrategy.TablePerType: - classesWithTables = modelRoot.Classes.Where(mc => !mc.IsDependentType && mc.GenerateCode).OrderBy(x => x.Name).ToArray(); - - break; - - case CodeStrategy.TablePerConcreteType: - classesWithTables = modelRoot.Classes.Where(mc => !mc.IsDependentType && !mc.IsAbstract && mc.GenerateCode).OrderBy(x => x.Name).ToArray(); - - break; - - case CodeStrategy.TablePerHierarchy: - classesWithTables = modelRoot.Classes.Where(mc => !mc.IsDependentType && mc.Superclass == null && mc.GenerateCode).OrderBy(x => x.Name).ToArray(); - - break; - } - - Output("using System;"); - Output("using System.Collections.Generic;"); - Output("using System.Linq;"); - Output("using System.ComponentModel.DataAnnotations.Schema;"); - Output("using Microsoft.EntityFrameworkCore;"); - NL(); - - BeginNamespace(modelRoot.Namespace); - - WriteDbContextComments(modelRoot); - - string baseClass = string.IsNullOrWhiteSpace(modelRoot.BaseClass) ? "Microsoft.EntityFrameworkCore.DbContext" : modelRoot.BaseClass; - Output($"{modelRoot.EntityContainerAccess.ToString().ToLower()} partial class {modelRoot.EntityContainerName} : {baseClass}"); - Output("{"); - - if (classesWithTables?.Any() == true) - WriteDbSetsEFCore(modelRoot); - - WriteConstructorsEFCore(modelRoot); - WriteOnConfiguringEFCore(modelRoot, segments); - WriteOnModelCreateEFCore(modelRoot, segments, classesWithTables); - - Output("}"); - - EndNamespace(modelRoot.Namespace); - } - - private void WriteDbSetsEFCore(ModelRoot modelRoot) - { - Output("#region DbSets"); - PluralizationService pluralizationService = ModelRoot.PluralizationService; - - foreach (ModelClass modelClass in modelRoot.Classes.Where(x => !x.IsDependentType).OrderBy(x => x.Name)) - { - string dbSetName; - - if (!string.IsNullOrEmpty(modelClass.DbSetName)) - dbSetName = modelClass.DbSetName; - else - { - dbSetName = pluralizationService?.IsSingular(modelClass.Name) == true - ? pluralizationService.Pluralize(modelClass.Name) - : modelClass.Name; - } - - if (!string.IsNullOrEmpty(modelClass.Summary)) - { - NL(); - Output("/// "); - WriteCommentBody($"Repository for {modelClass.FullName} - {modelClass.Summary}"); - Output("/// "); - } - - Output($"{modelRoot.DbSetAccess.ToString().ToLower()} virtual Microsoft.EntityFrameworkCore.DbSet<{modelClass.FullName}> {dbSetName} {{ get; set; }}"); - } - - Output("#endregion DbSets"); - NL(); - } - - private void WriteConstructorsEFCore(ModelRoot modelRoot) - { - if (!string.IsNullOrEmpty(modelRoot.ConnectionString) || !string.IsNullOrEmpty(modelRoot.ConnectionStringName)) - { - string connectionString = string.IsNullOrEmpty(modelRoot.ConnectionString) - ? $"Name={modelRoot.ConnectionStringName}" - : modelRoot.ConnectionString; - - Output("/// "); - Output("/// Default connection string"); - Output("/// "); - Output($"public static string ConnectionString {{ get; set; }} = @\"{connectionString}\";"); - NL(); - } - - Output("/// "); - Output($"public {modelRoot.EntityContainerName}(DbContextOptions<{modelRoot.EntityContainerName}> options) : base(options)"); - Output("{"); - Output("}"); - NL(); - - Output("partial void CustomInit(DbContextOptionsBuilder optionsBuilder);"); - NL(); - } - - private void WriteOnConfiguringEFCore(ModelRoot modelRoot, List segments) - { - Output("/// "); - Output("protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)"); - Output("{"); - - segments.Clear(); - - if (modelRoot.GetEntityFrameworkPackageVersionNum() >= 2.1 && modelRoot.LazyLoadingEnabled) - segments.Add("UseLazyLoadingProxies()"); - - if (segments.Any()) - { - segments.Insert(0, "optionsBuilder"); - - if (modelRoot.ChopMethodChains) - OutputChopped(segments); - else - Output(string.Join(".", segments) + ";"); - - NL(); - } - - Output("CustomInit(optionsBuilder);"); - Output("}"); - NL(); - } - - private void WriteOnModelCreateEFCore(ModelRoot modelRoot, List segments, ModelClass[] classesWithTables) - { - Output("partial void OnModelCreatingImpl(ModelBuilder modelBuilder);"); - Output("partial void OnModelCreatedImpl(ModelBuilder modelBuilder);"); - NL(); - - Output("/// "); - Output("protected override void OnModelCreating(ModelBuilder modelBuilder)"); - Output("{"); - Output("base.OnModelCreating(modelBuilder);"); - Output("OnModelCreatingImpl(modelBuilder);"); - NL(); - - if (!string.IsNullOrEmpty(modelRoot.DatabaseSchema)) - Output($"modelBuilder.HasDefaultSchema(\"{modelRoot.DatabaseSchema}\");"); - - List visited = new List(); - List foreignKeyColumns = new List(); - List declaredShadowProperties = new List(); - - foreach (ModelClass modelClass in modelRoot.Classes.OrderBy(x => x.Name)) - { - segments.Clear(); - foreignKeyColumns.Clear(); - declaredShadowProperties.Clear(); - NL(); - - // class level - bool isDependent = modelClass.IsDependentType; - segments.Add($"modelBuilder.{(isDependent ? "Owned" : "Entity")}<{modelClass.FullName}>()"); - - foreach (ModelAttribute transient in modelClass.Attributes.Where(x => !x.Persistent)) - segments.Add($"Ignore(t => t.{transient.Name})"); - - if (!isDependent) - { - // note: this must come before the 'ToTable' call or there's a runtime error - if (modelRoot.InheritanceStrategy == CodeStrategy.TablePerConcreteType && modelClass.Superclass != null) - segments.Add("Map(x => x.MapInheritedProperties())"); - - if (classesWithTables.Contains(modelClass)) - { - segments.Add(string.IsNullOrEmpty(modelClass.DatabaseSchema) || modelClass.DatabaseSchema == modelClass.ModelRoot.DatabaseSchema - ? $"ToTable(\"{modelClass.TableName}\")" - : $"ToTable(\"{modelClass.TableName}\", \"{modelClass.DatabaseSchema}\")"); - - // primary key code segments must be output last, since HasKey returns a different type - List identityAttributes = modelClass.AllIdentityAttributes.ToList(); - - if (identityAttributes.Count == 1) - segments.Add($"HasKey(t => t.{identityAttributes[0].Name})"); - else if (identityAttributes.Count > 1) - segments.Add($"HasKey(t => new {{ t.{string.Join(", t.", identityAttributes.Select(ia => ia.Name))} }})"); - } - } - - if (segments.Count > 1 || isDependent) - { - if (modelRoot.ChopMethodChains) - OutputChopped(segments); - else - Output(string.Join(".", segments) + ";"); - } - - if (isDependent) - continue; - - // attribute level - foreach (ModelAttribute modelAttribute in modelClass.Attributes.Where(x => x.Persistent && !SpatialTypesEFCore.Contains(x.Type))) - { - segments.Clear(); - - if ((modelAttribute.MaxLength ?? 0) > 0) - segments.Add($"HasMaxLength({modelAttribute.MaxLength.Value})"); - - if (modelAttribute.Required) - segments.Add("IsRequired()"); - - if (modelAttribute.ColumnName != modelAttribute.Name && !string.IsNullOrEmpty(modelAttribute.ColumnName)) - segments.Add($"HasColumnName(\"{modelAttribute.ColumnName}\")"); - - if (!modelAttribute.AutoProperty) - { - segments.Add($"HasField(\"{modelAttribute.BackingFieldName}\")"); - segments.Add($"UsePropertyAccessMode(PropertyAccessMode.{(modelAttribute.PersistencePoint == PersistencePointType.Field ? "Field" : "Property")})"); - } - - if (!string.IsNullOrEmpty(modelAttribute.ColumnType) && modelAttribute.ColumnType.ToLowerInvariant() != "default") - { - if (modelAttribute.ColumnType.ToLowerInvariant() == "varchar" || modelAttribute.ColumnType.ToLowerInvariant() == "nvarchar" || modelAttribute.ColumnType.ToLowerInvariant() == "char") - segments.Add($"HasColumnType(\"{modelAttribute.ColumnType}({(modelAttribute.MaxLength > 0 ? modelAttribute.MaxLength.ToString() : "max")})\")"); - else - segments.Add($"HasColumnType(\"{modelAttribute.ColumnType}\")"); - } - - if (modelAttribute.IsConcurrencyToken) - segments.Add("IsRowVersion()"); - - if (modelAttribute.IsIdentity) - { - segments.Add(modelAttribute.IdentityType == IdentityType.AutoGenerated - ? "ValueGeneratedOnAdd()" - : "ValueGeneratedNever()"); - } - - if (segments.Any()) - { - segments.Insert(0, $"modelBuilder.{(modelClass.IsDependentType ? "Owned" : "Entity")}<{modelClass.FullName}>()"); - segments.Insert(1, $"Property(t => t.{modelAttribute.Name})"); - - if (modelRoot.ChopMethodChains) - OutputChopped(segments); - else - Output(string.Join(".", segments) + ";"); - } - - if (modelAttribute.Indexed && !modelAttribute.IsIdentity) - { - segments.Clear(); - - segments.Add($"modelBuilder.Entity<{modelClass.FullName}>().HasIndex(t => t.{modelAttribute.Name})"); - - if (modelAttribute.IndexedUnique) - segments.Add("IsUnique()"); - - if (modelRoot.ChopMethodChains) - OutputChopped(segments); - else - Output(string.Join(".", segments) + ";"); - } - } - - bool hasDefinedConcurrencyToken = modelClass.AllAttributes.Any(x => x.IsConcurrencyToken); - - if (!hasDefinedConcurrencyToken && modelClass.EffectiveConcurrency == ConcurrencyOverride.Optimistic) - Output($@"modelBuilder.Entity<{modelClass.FullName}>().Property(""Timestamp"").IsConcurrencyToken();"); - - // Navigation endpoints are distingished as Source and Target. They are also distinguished as Principal - // and Dependent. How do these map? - // In the case of one-to-one or zero-to-one-to-zero-to-one, it's model dependent and the user has to tell us - // In all other cases, we can tell by the cardinalities of the associations - // What matters is the Principal and Dependent classifications, so we look at those. - // Source and Target are accidents of where the user started drawing the association. - - // navigation properties - - // ReSharper disable once LoopCanBePartlyConvertedToQuery - foreach (UnidirectionalAssociation association in Association.GetLinksToTargets(modelClass) - .OfType() - .Where(x => x.Persistent && !x.Target.IsDependentType)) - { - if (visited.Contains(association)) - continue; - - visited.Add(association); - - segments.Clear(); - segments.Add($"modelBuilder.Entity<{modelClass.FullName}>()"); - bool required = false; - - switch (association.TargetMultiplicity) // realized by property on source - { - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany: - if (association.SourceMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany || association.Source.ModelRoot.IsEFCore5Plus) - segments.Add($"HasMany(x => x.{association.TargetPropertyName})"); - - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.One: - segments.Add($"HasOne(x => x.{association.TargetPropertyName})"); - - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroOne: - segments.Add($"HasOne(x => x.{association.TargetPropertyName})"); - - break; - - //case Sawczyn.EFDesigner.EFModel.Multiplicity.OneMany: - // segments.Add($"HasMany(x => x.{association.TargetPropertyName})"); - // break; - } - - switch (association.SourceMultiplicity) // realized by shadow property on target - { - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany: - if (association.Source.ModelRoot.IsEFCore5Plus || association.TargetMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany) - segments.Add("WithMany()"); - - if (association.Source.ModelRoot.IsEFCore5Plus && association.TargetMultiplicity == Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany) - { - string tableMap = string.IsNullOrEmpty(association.JoinTableName) ? $"{association.Source.Name}_x_{association.TargetPropertyName}" : association.JoinTableName; - string suffix1 = association.Source == association.Target ? "A" : ""; - string suffix2 = association.Source == association.Target ? "B" : ""; - string sourceMap = string.Join(", ", association.Source.AllIdentityAttributeNames.Select(n => $@"""{association.Source.Name}_{n}{suffix1}""").ToList()); - string targetMap = string.Join(", ", association.Target.AllIdentityAttributeNames.Select(n => $@"""{association.Target.Name}_{n}{suffix2}""").ToList()); - - segments.Add(modelClass == association.Source - ? $@"Map(x => {{ x.ToTable(""{tableMap}""); x.MapLeftKey({sourceMap}); x.MapRightKey({targetMap}); }})" - : $@"Map(x => {{ x.ToTable(""{tableMap}""); x.MapLeftKey({targetMap}); x.MapRightKey({sourceMap}); }})"); - } break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.One: - segments.Add("WithOne()"); - - //segments.Add(association.TargetMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany - // ? $"HasForeignKey<{association.Source.FullName}>(\"{columnPrefix}{association.TargetPropertyName}_Id\")" - // : $"HasForeignKey(\"{columnPrefix}{association.TargetPropertyName}_Id\")"); - - required = true; - - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroOne: - segments.Add("WithOne()"); - - //segments.Add(association.TargetMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany - // ? $"HasForeignKey<{association.Source.FullName}>(\"{columnPrefix}{association.TargetPropertyName}_Id\")" - // : $"HasForeignKey(\"{columnPrefix}{association.TargetPropertyName}_Id\")"); - - break; - - //case Sawczyn.EFDesigner.EFModel.Multiplicity.OneMany: - // segments.Add("HasMany()"); - // break; - } - - string foreignKeySegment = CreateForeignKeySegmentEFCore(association, foreignKeyColumns); - - // can't include shadow properties twice - if (foreignKeySegment != null) - { - if (!foreignKeySegment.Contains("MapKey")) - segments.Add(foreignKeySegment); - else if (!declaredShadowProperties.Contains(foreignKeySegment)) - { - declaredShadowProperties.Add(foreignKeySegment); - segments.Add(foreignKeySegment); - } - } - - if (required) - segments.Add("IsRequired()"); - - if (association.TargetRole == EndpointRole.Principal || association.SourceRole == EndpointRole.Principal) - { - DeleteAction deleteAction = association.SourceRole == EndpointRole.Principal - ? association.SourceDeleteAction - : association.TargetDeleteAction; - - switch (deleteAction) - { - case DeleteAction.None: - segments.Add("OnDelete(DeleteBehavior.Restrict)"); - - break; - - case DeleteAction.Cascade: - segments.Add("OnDelete(DeleteBehavior.Cascade)"); - - break; - } - } - - if (modelRoot.ChopMethodChains) - OutputChopped(segments); - else - Output(string.Join(".", segments) + ";"); - } - - foreach (UnidirectionalAssociation association in Association.GetLinksToTargets(modelClass) - .OfType() - .Where(x => x.Persistent && x.Target.IsDependentType)) - { - if (association.TargetMultiplicity == Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroOne || association.TargetMultiplicity == Sawczyn.EFDesigner.EFModel.Multiplicity.One) - Output($"modelBuilder.Entity<{modelClass.FullName}>().OwnsOne(x => x.{association.TargetPropertyName});"); - else - Output($"// Dependent 1-many association seen ({association.TargetPropertyName}). Code generation still unsupported in designer."); - } - - // ReSharper disable once LoopCanBePartlyConvertedToQuery - foreach (BidirectionalAssociation association in Association.GetLinksToSources(modelClass) - .OfType() - .Where(x => x.Persistent)) - { - if (visited.Contains(association)) - continue; - - visited.Add(association); - - // TODO: fix cascade delete - bool required = false; - - segments.Clear(); - segments.Add($"modelBuilder.Entity<{modelClass.FullName}>()"); - - switch (association.SourceMultiplicity) // realized by property on target - { - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany: - if (association.TargetMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany || association.Source.ModelRoot.IsEFCore5Plus) - segments.Add($"HasMany(x => x.{association.SourcePropertyName})"); - - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.One: - segments.Add($"HasOne(x => x.{association.SourcePropertyName})"); - - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroOne: - segments.Add($"HasOne(x => x.{association.SourcePropertyName})"); - - break; - - //case Sawczyn.EFDesigner.EFModel.Multiplicity.OneMany: - // segments.Add($"HasMany(x => x.{association.SourcePropertyName})"); - // break; - } - - switch (association.TargetMultiplicity) // realized by property on source - { - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany: - // TODO: Implement many-to-many - if (association.Source.ModelRoot.IsEFCore5Plus || association.SourceMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany) - segments.Add($"WithMany(x => x.{association.TargetPropertyName})"); - - if (association.Source.ModelRoot.IsEFCore5Plus && association.SourceMultiplicity == Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany) - { - string tableMap = string.IsNullOrEmpty(association.JoinTableName) ? $"{association.Source.Name}_x_{association.TargetPropertyName}" : association.JoinTableName; - string suffix1 = association.Source == association.Target ? "A" : ""; - string suffix2 = association.Source == association.Target ? "B" : ""; - string sourceMap = string.Join(", ", association.Source.AllIdentityAttributeNames.Select(n => $@"""{association.Source.Name}_{n}{suffix1}""").ToList()); - string targetMap = string.Join(", ", association.Target.AllIdentityAttributeNames.Select(n => $@"""{association.Target.Name}_{n}{suffix2}""").ToList()); - - segments.Add(modelClass == association.Source - ? $@"Map(x => {{ x.ToTable(""{tableMap}""); x.MapLeftKey({sourceMap}); x.MapRightKey({targetMap}); }})" - : $@"Map(x => {{ x.ToTable(""{tableMap}""); x.MapLeftKey({targetMap}); x.MapRightKey({sourceMap}); }})"); - } - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.One: - segments.Add($"WithOne(x => x.{association.TargetPropertyName})"); - required = true; - - break; - - case Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroOne: - segments.Add($"WithOne(x => x.{association.TargetPropertyName})"); - - break; - - //case Sawczyn.EFDesigner.EFModel.Multiplicity.OneMany: - // segments.Add($"HasMany(x => x.{association.TargetPropertyName})"); - // break; - } - - string foreignKeySegment = CreateForeignKeySegmentEFCore(association, foreignKeyColumns); - - if (foreignKeySegment != null) - segments.Add(foreignKeySegment); - - if (required) - segments.Add("IsRequired()"); - - if (association.TargetRole == EndpointRole.Principal || association.SourceRole == EndpointRole.Principal) - { - DeleteAction deleteAction = association.SourceRole == EndpointRole.Principal - ? association.SourceDeleteAction - : association.TargetDeleteAction; - - switch (deleteAction) - { - case DeleteAction.None: - segments.Add("OnDelete(DeleteBehavior.Restrict)"); - - break; - - case DeleteAction.Cascade: - segments.Add("OnDelete(DeleteBehavior.Cascade)"); - - break; - } - } - - if (modelRoot.ChopMethodChains) - OutputChopped(segments); - else - Output(string.Join(".", segments) + ";"); - } - } - - NL(); - - Output("OnModelCreatedImpl(modelBuilder);"); - Output("}"); - } - - string CreateForeignKeySegmentEFCore(Association association, List foreignKeyColumns) - { - // foreign key definitions always go in the table representing the Dependent end of the association - // if there is no dependent end (i.e., many-to-many), there are no foreign keys - ModelClass principal; - ModelClass dependent; - - if (association.SourceRole == EndpointRole.Dependent) - { - dependent = association.Source; - principal = association.Target; - } - else if (association.TargetRole == EndpointRole.Dependent) - { - dependent = association.Target; - principal = association.Source; - } - else - return null; - - string columnName; - - if (string.IsNullOrWhiteSpace(association.FKPropertyName)) - { - // shadow properties - columnName = string.Join(", " - , principal.AllIdentityAttributes - .Select(a => CreateShadowPropertyName(association, foreignKeyColumns, a)) - .Select(s => $@"""{s.Trim()}""")); - } - else - { - // defined properties - foreignKeyColumns.AddRange(association.FKPropertyName.Split(',')); - columnName = string.Join(", ", association.FKPropertyName.Split(',').Select(s => $@"""{s.Trim()}""")); - } - - return association.SourceMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany - && association.TargetMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany - ? $"HasForeignKey<{dependent.FullName}>({columnName})" - : $"HasForeignKey({columnName})"; - } - } -} - - diff --git a/src/DslPackage/TextTemplates/EditingOnly/EFDesigner.cs b/src/DslPackage/TextTemplates/EditingOnly/EFDesigner.cs index d4bda4c57..058e9dd1b 100644 --- a/src/DslPackage/TextTemplates/EditingOnly/EFDesigner.cs +++ b/src/DslPackage/TextTemplates/EditingOnly/EFDesigner.cs @@ -285,7 +285,7 @@ void Output(string text) WriteLine(text); if (text.EndsWith("{")) - PushIndent(ModelRoot.UseTabs() ? "\t" : " "); + PushIndent(ModelRoot.UseTabs ? "\t" : " "); } void Output(string template, params object[] items) diff --git a/src/DslPackage/TextTemplates/EditingOnly/EFDesigner.ttinclude b/src/DslPackage/TextTemplates/EditingOnly/EFDesigner.ttinclude deleted file mode 100644 index 8a63743d6..000000000 --- a/src/DslPackage/TextTemplates/EditingOnly/EFDesigner.ttinclude +++ /dev/null @@ -1,1041 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Security; - -// ReSharper disable RedundantNameQualifier - -namespace Sawczyn.EFDesigner.EFModel.DslPackage.TextTemplates.EditingOnly -{ - [SuppressMessage("ReSharper", "UnusedMember.Local")] - [SuppressMessage("ReSharper", "UnusedMember.Global")] - partial class EditOnly - { - // EFDesigner v2.0.5.7 - // Copyright (c) 2017-2020 Michael Sawczyn - // https://github.com/msawczyn/EFDesigner - - /************************************************** - * Code generation methods and data common to EF6 and EFCore - */ - - string[] NonNullableTypes - { - get - { - return new[] - { - "Binary" - , "Geography" - , "GeographyCollection" - , "GeographyLineString" - , "GeographyMultiLineString" - , "GeographyMultiPoint" - , "GeographyMultiPolygon" - , "GeographyPoint" - , "GeographyPolygon" - , "Geometry" - , "GeometryCollection" - , "GeometryLineString" - , "GeometryMultiLineString" - , "GeometryMultiPoint" - , "GeometryMultiPolygon" - , "GeometryPoint" - , "GeometryPolygon" - , "String" - }; - } - } - - private static string CreateShadowPropertyName(Association association, List foreignKeyColumns, ModelAttribute identityAttribute) - { - string shadowNameBase = association.SourceRole == EndpointRole.Dependent - ? association.TargetPropertyName - : association is BidirectionalAssociation b - ? b.SourcePropertyName - : $"{association.Source.Name}.{association.TargetPropertyName}"; - - string shadowPropertyName = $"{shadowNameBase}_{identityAttribute.Name}"; - - int index = 0; - - while (foreignKeyColumns.Contains(shadowPropertyName)) - shadowPropertyName = $"{shadowNameBase}{++index}_{identityAttribute.Name}"; - - return shadowPropertyName; - } - - bool AllSuperclassesAreNullOrAbstract(ModelClass modelClass) - { - ModelClass superClass = modelClass.Superclass; - - while (superClass != null) - { - if (!superClass.IsAbstract) - return false; - - superClass = superClass.Superclass; - } - - return true; - } - - void BeginNamespace(string ns) - { - if (!string.IsNullOrEmpty(ns)) - { - Output($"namespace {ns}"); - Output("{"); - } - } - - void EndNamespace(string ns) - { - if (!string.IsNullOrEmpty(ns)) - Output("}"); - } - - string FullyQualified(ModelRoot modelRoot, string typeName) - { - string[] parts = typeName.Split('.'); - - if (parts.Length == 1) - return typeName; - - string simpleName = parts[0]; - ModelEnum modelEnum = modelRoot.Store.ElementDirectory.AllElements.OfType().FirstOrDefault(e => e.Name == simpleName); - - return modelEnum != null - ? $"{modelEnum.FullName}.{parts.Last()}" - : typeName; - } - - void GeneratePropertyAnnotations(ModelAttribute modelAttribute) - { - if (modelAttribute.Persistent) - { - if (modelAttribute.IsIdentity) - Output("[Key]"); - - if (modelAttribute.IsConcurrencyToken) - Output("[ConcurrencyCheck]"); - } - else - Output("[NotMapped]"); - - if (modelAttribute.Required) - Output("[Required]"); - - if (modelAttribute.FQPrimitiveType == "string") - { - if (modelAttribute.MinLength > 0) - Output($"[MinLength({modelAttribute.MinLength})]"); - - if (modelAttribute.MaxLength > 0) - { - Output($"[MaxLength({modelAttribute.MaxLength})]"); - Output($"[StringLength({modelAttribute.MaxLength})]"); - } - } - - if (!string.IsNullOrWhiteSpace(modelAttribute.DisplayText)) - Output($"[Display(Name=\"{modelAttribute.DisplayText}\")]"); - } - - string GetFullContainerName(string containerType, string payloadType) - { - string result; - - switch (containerType) - { - case "HashSet": - result = "System.Collections.Generic.HashSet"; - - break; - - case "LinkedList": - result = "System.Collections.Generic.LinkedList"; - - break; - - case "List": - result = "System.Collections.Generic.List"; - - break; - - case "SortedSet": - result = "System.Collections.Generic.SortedSet"; - - break; - - case "Collection": - result = "System.Collections.ObjectModel.Collection"; - - break; - - case "ObservableCollection": - result = "System.Collections.ObjectModel.ObservableCollection"; - - break; - - case "BindingList": - result = "System.ComponentModel.BindingList"; - - break; - - default: - result = containerType; - - break; - } - - if (result.EndsWith("")) - result = result.Replace("", $"<{payloadType}>"); - - return result; - } - - List GetRequiredParameterNames(ModelClass modelClass, bool? publicOnly = null) - { - List requiredParameterNames = modelClass.AllRequiredAttributes - .Where(x => (!x.IsIdentity || x.IdentityType == IdentityType.Manual) - && !x.IsConcurrencyToken - && (x.SetterVisibility == SetterAccessModifier.Public || publicOnly != false) - && string.IsNullOrEmpty(x.InitialValue)) - .Select(x => x.Name.ToLower()) - .ToList(); - - requiredParameterNames.AddRange(modelClass.AllRequiredNavigationProperties() - .Where(np => np.AssociationObject.SourceMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.One - || np.AssociationObject.TargetMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.One) - .Select(x => x.PropertyName.ToLower())); - - requiredParameterNames.AddRange(modelClass.AllRequiredAttributes - .Where(x => (!x.IsIdentity || x.IdentityType == IdentityType.Manual) - && !x.IsConcurrencyToken - && (x.SetterVisibility == SetterAccessModifier.Public || publicOnly != false) - && !string.IsNullOrEmpty(x.InitialValue)) - .Select(x => x.Name.ToLower())); - - return requiredParameterNames; - } - - List GetRequiredParameters(ModelClass modelClass, bool? haveDefaults, bool? publicOnly = null) - { - List requiredParameters = new List(); - - if (haveDefaults != true) - { - requiredParameters.AddRange(modelClass.AllRequiredAttributes - .Where(x => (!x.IsIdentity || x.IdentityType == IdentityType.Manual) - && !x.IsConcurrencyToken - && (x.SetterVisibility == SetterAccessModifier.Public || publicOnly != false) - && string.IsNullOrEmpty(x.InitialValue)) - .Select(x => $"{x.FQPrimitiveType} {x.Name.ToLower()}")); - - // don't use 1..1 associations in constructor parameters. Becomes a Catch-22 scenario. - requiredParameters.AddRange(modelClass.AllRequiredNavigationProperties() - .Where(np => np.AssociationObject.SourceMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.One - || np.AssociationObject.TargetMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.One) - .Select(x => $"{x.ClassType.FullName} {x.PropertyName.ToLower()}")); - } - - if (haveDefaults != false) - { - requiredParameters.AddRange(modelClass.AllRequiredAttributes - .Where(x => (!x.IsIdentity || x.IdentityType == IdentityType.Manual) - && !x.IsConcurrencyToken - && (x.SetterVisibility == SetterAccessModifier.Public || publicOnly != false) - && !string.IsNullOrEmpty(x.InitialValue)) - .Select(x => - { - string quote = x.PrimitiveType == "string" - ? "\"" - : x.PrimitiveType == "char" - ? "'" - : string.Empty; - - string value = FullyQualified(modelClass.ModelRoot, quote.Length > 0 - ? x.InitialValue.Trim(quote[0]) - : x.InitialValue); - - return $"{x.FQPrimitiveType} {x.Name.ToLower()} = {quote}{value}{quote}"; - })); - } - - return requiredParameters; - } - - bool IsNullable(ModelAttribute modelAttribute) - { - return !modelAttribute.Required && !modelAttribute.IsIdentity && !modelAttribute.IsConcurrencyToken && !NonNullableTypes.Contains(modelAttribute.Type); - } - - void NL() - { - WriteLine(string.Empty); - } - - void Output(string text) - { - if (text.StartsWith("}")) - PopIndent(); - - WriteLine(text); - - if (text.EndsWith("{")) - PushIndent(ModelRoot.UseTabs() ? "\t" : " "); - } - - void Output(string template, params object[] items) - { - string text = string.Format(template, items); - Output(text); - } - - void OutputChopped(IEnumerable segments) - { - string[] segmentArray = segments?.ToArray() ?? new string[0]; - - if (!segmentArray.Any()) - return; - - int indent = segmentArray[0].IndexOf('.'); - - if (indent == -1) - { - if (segmentArray.Length > 1) - { - segmentArray[0] = $"{segmentArray[0]}.{segmentArray[1]}"; - indent = segmentArray[0].IndexOf('.'); - segmentArray = segmentArray.Where((source, index) => index != 1).ToArray(); - } - } - - for (int index = 1; index < segmentArray.Length; ++index) - segmentArray[index] = $"{new string(' ', indent)}.{segmentArray[index]}"; - - if (!segmentArray[segmentArray.Length - 1].Trim().EndsWith(";")) - segmentArray[segmentArray.Length - 1] = segmentArray[segmentArray.Length - 1] + ";"; - - foreach (string segment in segmentArray) - Output(segment); - } - - void WriteClass(ModelClass modelClass) - { - Output("using System;"); - Output("using System.Collections.Generic;"); - Output("using System.Collections.ObjectModel;"); - Output("using System.ComponentModel;"); - Output("using System.ComponentModel.DataAnnotations;"); - Output("using System.ComponentModel.DataAnnotations.Schema;"); - Output("using System.Linq;"); - Output("using System.Runtime.CompilerServices;"); - List additionalUsings = GetAdditionalUsingStatementsEF6(modelClass.ModelRoot); - - if (additionalUsings.Any()) - Output(string.Join("\n", additionalUsings)); - - NL(); - - BeginNamespace(modelClass.EffectiveNamespace); - - string isAbstract = modelClass.IsAbstract - ? "abstract " - : string.Empty; - - List bases = new List(); - - if (modelClass.Superclass != null) - bases.Add(modelClass.Superclass.FullName); - - if (!string.IsNullOrEmpty(modelClass.CustomInterfaces)) - bases.AddRange(modelClass.CustomInterfaces.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)); - - if (modelClass.ImplementNotify) - bases.Add("INotifyPropertyChanged"); - - string baseClass = string.Join(", ", bases.Select(x => x.Trim())); - - if (!string.IsNullOrEmpty(modelClass.Summary)) - { - Output("/// "); - WriteCommentBody(modelClass.Summary); - Output("/// "); - } - - if (!string.IsNullOrEmpty(modelClass.Description)) - { - Output("/// "); - WriteCommentBody(modelClass.Description); - Output("/// "); - } - - if (!string.IsNullOrWhiteSpace(modelClass.CustomAttributes)) - Output($"[{modelClass.CustomAttributes.Trim('[', ']')}]"); - - Output(baseClass.Length > 0 - ? $"public {isAbstract}partial class {modelClass.Name}: {baseClass}" - : $"public {isAbstract}partial class {modelClass.Name}"); - - Output("{"); - - WriteConstructor(modelClass); - WriteProperties(modelClass); - WriteNavigationProperties(modelClass); - WriteNotifyPropertyChanged(modelClass); - - Output("}"); - - EndNamespace(modelClass.EffectiveNamespace); - NL(); - } - - void WriteCommentBody(string comment) - { - int chunkSize = 80; - string[] parts = comment.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); - - foreach (string value in parts) - { - string text = value; - - while (text.Length > 0) - { - string outputText = text; - - if (outputText.Length > chunkSize) - { - outputText = (text.IndexOf(' ', chunkSize) > 0 - ? text.Substring(0, text.IndexOf(' ', chunkSize)) - : text).Trim(); - - text = text.Substring(outputText.Length).Trim(); - } - else - text = string.Empty; - - //Output("/// " + outputText.Replace("<", "{").Replace(">", "}")); - Output("/// " + SecurityElement.Escape(outputText)); - } - } - } - - void WriteConstructor(ModelClass modelClass) - { - Output("partial void Init();"); - NL(); - - /***********************************************************************/ - // Default constructor - /***********************************************************************/ - - bool hasRequiredParameters = GetRequiredParameters(modelClass, false).Any(); - - bool hasOneToOneAssociations = modelClass.AllRequiredNavigationProperties() - .Any(np => np.AssociationObject.SourceMultiplicity == Sawczyn.EFDesigner.EFModel.Multiplicity.One - && np.AssociationObject.TargetMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.One); - - string visibility = (hasRequiredParameters || modelClass.IsAbstract) && !modelClass.IsDependentType - ? "protected" - : "public"; - - if (visibility == "public") - { - Output("/// "); - Output("/// Default constructor"); - Output("/// "); - } - else if (modelClass.IsAbstract) - { - Output("/// "); - Output("/// Default constructor. Protected due to being abstract."); - Output("/// "); - } - else if (hasRequiredParameters) - { - Output("/// "); - Output("/// Default constructor. Protected due to required properties, but present because EF needs it."); - Output("/// "); - } - - List remarks = new List(); - - if (hasOneToOneAssociations) - { - List oneToOneAssociations = modelClass.AllRequiredNavigationProperties() - .Where(np => np.AssociationObject.SourceMultiplicity == Sawczyn.EFDesigner.EFModel.Multiplicity.One - && np.AssociationObject.TargetMultiplicity == Sawczyn.EFDesigner.EFModel.Multiplicity.One) - .Select(np => np.AssociationObject) - .ToList(); - - List otherEndsOneToOne = oneToOneAssociations.Where(a => a.Source != modelClass).Select(a => a.Target) - .Union(oneToOneAssociations.Where(a => a.Target != modelClass).Select(a => a.Source)) - .ToList(); - - if (oneToOneAssociations.Any(a => a.Source.Name == modelClass.Name && a.Target.Name == modelClass.Name)) - otherEndsOneToOne.Add(modelClass); - - if (otherEndsOneToOne.Any()) - { - string nameList = otherEndsOneToOne.Count == 1 - ? otherEndsOneToOne.First().Name - : string.Join(", ", otherEndsOneToOne.Take(otherEndsOneToOne.Count - 1).Select(c => c.Name)) - + " and " - + (otherEndsOneToOne.Last().Name != modelClass.Name - ? otherEndsOneToOne.Last().Name - : "itself"); - - remarks.Add($"// NOTE: This class has one-to-one associations with {nameList}."); - remarks.Add("// One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other."); - } - } - - Output(modelClass.Superclass != null - ? $"{visibility} {modelClass.Name}(): base()" - : $"{visibility} {modelClass.Name}()"); - - Output("{"); - - if (remarks.Count > 0) - { - foreach (string remark in remarks) - Output(remark); - - NL(); - } - - WriteDefaultConstructorBody(modelClass); - - Output("}"); - NL(); - - if (visibility != "public" && !modelClass.IsAbstract) - { - Output("/// "); - Output("/// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving."); - Output("/// "); - Output($"public static {modelClass.Name} Create{modelClass.Name}Unsafe()"); - Output("{"); - Output($"return new {modelClass.Name}();"); - Output("}"); - NL(); - } - - /***********************************************************************/ - // Constructor with required parameters (if necessary) - /***********************************************************************/ - - if (hasRequiredParameters) - { - visibility = modelClass.IsAbstract - ? "protected" - : "public"; - - Output("/// "); - Output("/// Public constructor with required data"); - Output("/// "); - - WriteConstructorComments(modelClass); - Output($"{visibility} {modelClass.Name}({string.Join(", ", GetRequiredParameters(modelClass, null))})"); - Output("{"); - - if (remarks.Count > 0) - { - foreach (string remark in remarks) - Output(remark); - - NL(); - } - - foreach (ModelAttribute requiredAttribute in modelClass.AllRequiredAttributes - .Where(x => (!x.IsIdentity || x.IdentityType == IdentityType.Manual) - && !x.IsConcurrencyToken - && x.SetterVisibility == SetterAccessModifier.Public)) - { - if (requiredAttribute.Type == "String") - Output($"if (string.IsNullOrEmpty({requiredAttribute.Name.ToLower()})) throw new ArgumentNullException(nameof({requiredAttribute.Name.ToLower()}));"); - else if (requiredAttribute.Type.StartsWith("Geo")) - Output($"if ({requiredAttribute.Name.ToLower()} == null) throw new ArgumentNullException(nameof({requiredAttribute.Name.ToLower()}));"); - - Output($"this.{requiredAttribute.Name} = {requiredAttribute.Name.ToLower()};"); - NL(); - } - - foreach (ModelAttribute modelAttribute in modelClass.Attributes.Where(x => x.SetterVisibility == SetterAccessModifier.Public - && !x.Required - && !string.IsNullOrEmpty(x.InitialValue) - && x.InitialValue != "null")) - { - string quote = modelAttribute.Type == "String" - ? "\"" - : modelAttribute.Type == "Char" - ? "'" - : string.Empty; - - Output(quote.Length > 0 - ? $"this.{modelAttribute.Name} = {quote}{FullyQualified(modelClass.ModelRoot, modelAttribute.InitialValue.Trim(quote[0]))}{quote};" - : $"this.{modelAttribute.Name} = {quote}{FullyQualified(modelClass.ModelRoot, modelAttribute.InitialValue)}{quote};"); - } - - foreach (NavigationProperty requiredNavigationProperty in modelClass.AllRequiredNavigationProperties() - .Where(np => np.AssociationObject.SourceMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.One - || np.AssociationObject.TargetMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.One)) - { - string parameterName = requiredNavigationProperty.PropertyName.ToLower(); - Output($"if ({parameterName} == null) throw new ArgumentNullException(nameof({parameterName}));"); - - if (requiredNavigationProperty.IsCollection) - Output($"{requiredNavigationProperty.PropertyName}.Add({parameterName});"); - else if (requiredNavigationProperty.ConstructorParameterOnly) - { - UnidirectionalAssociation association = requiredNavigationProperty.AssociationObject as UnidirectionalAssociation; - - Output(association.TargetMultiplicity == Sawczyn.EFDesigner.EFModel.Multiplicity.ZeroMany - ? $"{requiredNavigationProperty.PropertyName}.{association.TargetPropertyName}.Add(this);" - : $"{requiredNavigationProperty.PropertyName}.{association.TargetPropertyName} = this;"); - } - else - Output($"this.{requiredNavigationProperty.PropertyName} = {parameterName};"); - - NL(); - } - - foreach (NavigationProperty navigationProperty in modelClass.LocalNavigationProperties() - .Where(x => x.AssociationObject.Persistent && (x.IsCollection || x.ClassType.IsDependentType) && !x.ConstructorParameterOnly)) - { - if (!navigationProperty.IsCollection) - Output($"this.{navigationProperty.PropertyName} = new {navigationProperty.ClassType.FullName}();"); - else - { - string collectionType = GetFullContainerName(navigationProperty.AssociationObject.CollectionClass, navigationProperty.ClassType.FullName); - Output($"this.{navigationProperty.PropertyName} = new {collectionType}();"); - } - } - - NL(); - Output("Init();"); - Output("}"); - NL(); - - if (!modelClass.IsAbstract) - { - Output("/// "); - Output("/// Static create function (for use in LINQ queries, etc.)"); - Output("/// "); - WriteConstructorComments(modelClass); - - string newToken = string.Empty; - List requiredParameters = GetRequiredParameters(modelClass, null); - - if (!AllSuperclassesAreNullOrAbstract(modelClass)) - { - List superclassRequiredParameters = GetRequiredParameters(modelClass.Superclass, null); - - if (!requiredParameters.Except(superclassRequiredParameters).Any()) - newToken = "new "; - } - - Output($"public static {newToken}{modelClass.Name} Create({string.Join(", ", GetRequiredParameters(modelClass, null))})"); - Output("{"); - Output($"return new {modelClass.Name}({string.Join(", ", GetRequiredParameterNames(modelClass))});"); - Output("}"); - NL(); - } - } - } - - void WriteConstructorComments(ModelClass modelClass) - { - foreach (ModelAttribute requiredAttribute in modelClass.AllRequiredAttributes.Where(x => (!x.IsIdentity || x.IdentityType == IdentityType.Manual) - && !x.IsConcurrencyToken - && x.SetterVisibility == SetterAccessModifier.Public)) - Output($@"/// {SecurityElement.Escape(requiredAttribute.Summary)}"); - - // TODO: Add comment if available - foreach (NavigationProperty requiredNavigationProperty in modelClass.AllRequiredNavigationProperties() - .Where(np => np.AssociationObject.SourceMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.One - || np.AssociationObject.TargetMultiplicity != Sawczyn.EFDesigner.EFModel.Multiplicity.One)) - Output($@"/// "); - } - - void WriteDefaultConstructorBody(ModelClass modelClass) - { - int lineCount = 0; - - foreach (ModelAttribute modelAttribute in modelClass.Attributes.Where(x => x.SetterVisibility == SetterAccessModifier.Public - && !string.IsNullOrEmpty(x.InitialValue) - && x.InitialValue.Trim('"') != "null")) - { - string quote = modelAttribute.Type == "String" - ? "\"" - : modelAttribute.Type == "Char" - ? "'" - : string.Empty; - - Output(quote.Length == 1 - ? $"{modelAttribute.Name} = {quote}{FullyQualified(modelClass.ModelRoot, modelAttribute.InitialValue.Trim(quote[0]))}{quote};" - : $"{modelAttribute.Name} = {quote}{FullyQualified(modelClass.ModelRoot, modelAttribute.InitialValue)}{quote};"); - - ++lineCount; - } - - foreach (NavigationProperty navigationProperty in modelClass.LocalNavigationProperties() - .Where(x => x.AssociationObject.Persistent && (x.IsCollection || x.ClassType.IsDependentType) && !x.ConstructorParameterOnly)) - { - if (navigationProperty.ClassType.IsDependentType) - Output($"{navigationProperty.PropertyName} = new {navigationProperty.ClassType.FullName}();"); - else - { - string collectionType = GetFullContainerName(navigationProperty.AssociationObject.CollectionClass, navigationProperty.ClassType.FullName); - Output($"{navigationProperty.PropertyName} = new {collectionType}();"); - } - - ++lineCount; - } - - if (lineCount > 0) - NL(); - - Output("Init();"); - } - - void WriteEnum(ModelEnum modelEnum) - { - Output("using System;"); - NL(); - - BeginNamespace(modelEnum.EffectiveNamespace); - - if (!string.IsNullOrEmpty(modelEnum.Summary)) - { - Output("/// "); - WriteCommentBody(modelEnum.Summary); - Output("/// "); - } - - if (!string.IsNullOrEmpty(modelEnum.Description)) - { - Output("/// "); - WriteCommentBody(modelEnum.Description); - Output("/// "); - } - - if (modelEnum.IsFlags) - Output("[Flags]"); - - if (!string.IsNullOrWhiteSpace(modelEnum.CustomAttributes)) - Output($"[{modelEnum.CustomAttributes.Trim('[', ']')}]"); - - Output($"public enum {modelEnum.Name} : {modelEnum.ValueType}"); - Output("{"); - - ModelEnumValue[] values = modelEnum.Values.ToArray(); - - for (int index = 0; index < values.Length; ++index) - { - if (!string.IsNullOrEmpty(values[index].Summary)) - { - Output("/// "); - WriteCommentBody(values[index].Summary); - Output("/// "); - } - - if (!string.IsNullOrEmpty(values[index].Description)) - { - Output("/// "); - WriteCommentBody(values[index].Description); - Output("/// "); - } - - if (!string.IsNullOrWhiteSpace(values[index].CustomAttributes)) - Output($"[{values[index].CustomAttributes.Trim('[', ']')}]"); - - if (!string.IsNullOrWhiteSpace(values[index].DisplayText)) - Output($"[System.ComponentModel.DataAnnotations.Display(Name=\"{values[index].DisplayText}\")]"); - - Output(string.IsNullOrEmpty(values[index].Value) - ? $"{values[index].Name}{(index < values.Length - 1 ? "," : string.Empty)}" - : $"{values[index].Name} = {values[index].Value}{(index < values.Length - 1 ? "," : string.Empty)}"); - } - - Output("}"); - - EndNamespace(modelEnum.EffectiveNamespace); - } - - void WriteNavigationProperties(ModelClass modelClass) - { - if (!modelClass.LocalNavigationProperties().Any(x => x.AssociationObject.Persistent)) - return; - - Output("/*************************************************************************"); - Output(" * Navigation properties"); - Output(" *************************************************************************/"); - NL(); - - foreach (NavigationProperty navigationProperty in modelClass.LocalNavigationProperties().Where(x => !x.ConstructorParameterOnly)) - { - string type = navigationProperty.IsCollection - ? $"ICollection<{navigationProperty.ClassType.FullName}>" - : navigationProperty.ClassType.FullName; - - if (!navigationProperty.IsCollection && !navigationProperty.IsAutoProperty) - { - Output($"protected {type} _{navigationProperty.PropertyName};"); - Output($"partial void Set{navigationProperty.PropertyName}({type} oldValue, ref {type} newValue);"); - Output($"partial void Get{navigationProperty.PropertyName}(ref {type} result);"); - - NL(); - } - - List comments = new List(); - - if (navigationProperty.Required) - comments.Add("Required"); - - string comment = comments.Count > 0 - ? string.Join(", ", comments) - : string.Empty; - - if (!string.IsNullOrEmpty(navigationProperty.Summary) || !string.IsNullOrEmpty(comment)) - { - Output("/// "); - - if (!string.IsNullOrEmpty(comment) && !string.IsNullOrEmpty(navigationProperty.Summary)) - comment = comment + "
"; - - if (!string.IsNullOrEmpty(comment)) - WriteCommentBody(comment); - - if (!string.IsNullOrEmpty(navigationProperty.Summary)) - WriteCommentBody(navigationProperty.Summary); - - Output("///
"); - } - - if (!string.IsNullOrEmpty(navigationProperty.Description)) - { - Output("/// "); - WriteCommentBody(navigationProperty.Description); - Output("/// "); - } - - if (!string.IsNullOrWhiteSpace(navigationProperty.CustomAttributes)) - Output($"[{navigationProperty.CustomAttributes.Trim('[', ']')}]"); - - if (!string.IsNullOrWhiteSpace(navigationProperty.DisplayText)) - Output($"[Display(Name=\"{navigationProperty.DisplayText}\")]"); - - if (navigationProperty.IsCollection) - Output($"public virtual {type} {navigationProperty.PropertyName} {{ get; protected set; }}"); - else if (navigationProperty.IsAutoProperty) - Output($"public virtual {type} {navigationProperty.PropertyName} {{ get; set; }}"); - else - { - Output($"public virtual {type} {navigationProperty.PropertyName}"); - Output("{"); - Output("get"); - Output("{"); - Output($"{type} value = _{navigationProperty.PropertyName};"); - Output($"Get{navigationProperty.PropertyName}(ref value);"); - Output($"return (_{navigationProperty.PropertyName} = value);"); - Output("}"); - Output("set"); - Output("{"); - Output($"{type} oldValue = _{navigationProperty.PropertyName};"); - Output($"Set{navigationProperty.PropertyName}(oldValue, ref value);"); - Output("if (oldValue != value)"); - Output("{"); - Output($"_{navigationProperty.PropertyName} = value;"); - - if (navigationProperty.ImplementNotify) - Output("OnPropertyChanged();"); - - Output("}"); - Output("}"); - Output("}"); - } - - NL(); - } - } - - void WriteNotifyPropertyChanged(ModelClass modelClass) - { - if (modelClass.ImplementNotify || modelClass.LocalNavigationProperties().Any(x => x.ImplementNotify) || modelClass.Attributes.Any(x => x.ImplementNotify)) - { - string modifier = modelClass.Superclass != null && modelClass.Superclass.ImplementNotify - ? "override" - : "virtual"; - - Output($"public {modifier} event PropertyChangedEventHandler PropertyChanged;"); - NL(); - Output($"protected {modifier} void OnPropertyChanged([CallerMemberName] string propertyName = null)"); - Output("{"); - Output("PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));"); - Output("}"); - NL(); - } - } - - void WriteProperties(ModelClass modelClass) - { - Output("/*************************************************************************"); - Output(" * Properties"); - Output(" *************************************************************************/"); - NL(); - - List segments = new List(); - - foreach (ModelAttribute modelAttribute in modelClass.Attributes) - { - segments.Clear(); - - if (modelAttribute.IsIdentity) - segments.Add("Identity"); - - if (modelAttribute.Indexed) - segments.Add("Indexed"); - - if (modelAttribute.Required || modelAttribute.IsIdentity) - segments.Add("Required"); - - if (modelAttribute.MinLength > 0) - segments.Add($"Min length = {modelAttribute.MinLength}"); - - if (modelAttribute.MaxLength > 0) - segments.Add($"Max length = {modelAttribute.MaxLength}"); - - if (!string.IsNullOrEmpty(modelAttribute.InitialValue)) - { - string quote = modelAttribute.PrimitiveType == "string" - ? "\"" - : modelAttribute.PrimitiveType == "char" - ? "'" - : string.Empty; - - segments.Add($"Default value = {quote}{FullyQualified(modelClass.ModelRoot, modelAttribute.InitialValue.Trim('"'))}{quote}"); - } - - string nullable = IsNullable(modelAttribute) - ? "?" - : string.Empty; - - if (!modelAttribute.IsConcurrencyToken && !modelAttribute.AutoProperty) - { - string visibility = modelAttribute.Indexed ? "internal" : "protected"; - Output("/// "); - Output($"/// Backing field for {modelAttribute.Name}"); - Output("/// "); - Output($"{visibility} {modelAttribute.FQPrimitiveType}{nullable} {modelAttribute.BackingFieldName};"); - Output("/// "); - Output($"/// When provided in a partial class, allows value of {modelAttribute.Name} to be changed before setting."); - Output("/// "); - Output($"partial void Set{modelAttribute.Name}({modelAttribute.FQPrimitiveType}{nullable} oldValue, ref {modelAttribute.FQPrimitiveType}{nullable} newValue);"); - Output("/// "); - Output($"/// When provided in a partial class, allows value of {modelAttribute.Name} to be changed before returning."); - Output("/// "); - Output($"partial void Get{modelAttribute.Name}(ref {modelAttribute.FQPrimitiveType}{nullable} result);"); - - NL(); - } - - if (!string.IsNullOrEmpty(modelAttribute.Summary) || segments.Any()) - { - Output("/// "); - - if (segments.Any()) - WriteCommentBody($"{string.Join(", ", segments)}"); - - if (!string.IsNullOrEmpty(modelAttribute.Summary)) - WriteCommentBody(modelAttribute.Summary); - - Output("/// "); - } - - if (!string.IsNullOrEmpty(modelAttribute.Description)) - { - Output("/// "); - WriteCommentBody(modelAttribute.Description); - Output("/// "); - } - - string setterVisibility = (modelAttribute.IsIdentity && modelAttribute.IdentityType != IdentityType.Manual) || modelAttribute.SetterVisibility == SetterAccessModifier.Protected - ? "protected " - : modelAttribute.SetterVisibility == SetterAccessModifier.Internal - ? "internal " - : string.Empty; - - GeneratePropertyAnnotations(modelAttribute); - - if (!string.IsNullOrWhiteSpace(modelAttribute.CustomAttributes)) - Output($"[{modelAttribute.CustomAttributes.Trim('[', ']')}]"); - - if (modelAttribute.IsConcurrencyToken || modelAttribute.AutoProperty) - Output($"public {modelAttribute.FQPrimitiveType}{nullable} {modelAttribute.Name} {{ get; {setterVisibility}set; }}"); - else - { - Output($"public {modelAttribute.FQPrimitiveType}{nullable} {modelAttribute.Name}"); - Output("{"); - Output("get"); - Output("{"); - Output($"{modelAttribute.FQPrimitiveType}{nullable} value = {modelAttribute.BackingFieldName};"); - Output($"Get{modelAttribute.Name}(ref value);"); - Output($"return ({modelAttribute.BackingFieldName} = value);"); - Output("}"); - Output($"{setterVisibility}set"); - Output("{"); - Output($"{modelAttribute.FQPrimitiveType}{nullable} oldValue = {modelAttribute.BackingFieldName};"); - Output($"Set{modelAttribute.Name}(oldValue, ref value);"); - Output("if (oldValue != value)"); - Output("{"); - Output($"{modelAttribute.BackingFieldName} = value;"); - - if (modelAttribute.ImplementNotify) - Output("OnPropertyChanged();"); - - Output("}"); - Output("}"); - Output("}"); - } - - NL(); - } - - if (!modelClass.AllAttributes.Any(x => x.IsConcurrencyToken) - && (modelClass.Concurrency == ConcurrencyOverride.Optimistic || modelClass.ModelRoot.ConcurrencyDefault == Concurrency.Optimistic)) - { - Output("/// "); - Output("/// Concurrency token"); - Output("/// "); - Output("[Timestamp]"); - Output("public Byte[] Timestamp { get; set; }"); - NL(); - } - } - - private void WriteDbContextComments(ModelRoot modelRoot) - { - if (!string.IsNullOrEmpty(modelRoot.Summary)) - { - Output("/// "); - WriteCommentBody(modelRoot.Summary); - Output("/// "); - - if (!string.IsNullOrEmpty(modelRoot.Description)) - { - Output("/// "); - WriteCommentBody(modelRoot.Description); - Output("/// "); - } - } - else - Output("/// "); - } - } -} - - diff --git a/src/Testing/Sandbox/Sandbox_EF6/EFModel1.cs b/src/Testing/Sandbox/Sandbox_EF6/EFModel1.cs index 2edc99e3e..6153a7d78 100644 --- a/src/Testing/Sandbox/Sandbox_EF6/EFModel1.cs +++ b/src/Testing/Sandbox/Sandbox_EF6/EFModel1.cs @@ -1 +1 @@ -ErrorGeneratingOutput \ No newline at end of file + diff --git a/src/Testing/Sandbox/Sandbox_EF6/EFModel1.efmodel b/src/Testing/Sandbox/Sandbox_EF6/EFModel1.efmodel index d81999922..fb251a6f5 100644 --- a/src/Testing/Sandbox/Sandbox_EF6/EFModel1.efmodel +++ b/src/Testing/Sandbox/Sandbox_EF6/EFModel1.efmodel @@ -1,5 +1,5 @@  - + diff --git a/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Context2.generated.cs b/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Context2.generated.cs index bee8ee78a..49c6c1dec 100644 --- a/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Context2.generated.cs +++ b/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Context2.generated.cs @@ -22,102 +22,102 @@ namespace MultiContext.Context2 { - /// - public partial class Context2 : DbContext - { - #region DbSets - public virtual System.Data.Entity.DbSet Bases { get; set; } - public virtual System.Data.Entity.DbSet Entity1 { get; set; } - public virtual System.Data.Entity.DbSet Entity2 { get; set; } - public virtual System.Data.Entity.DbSet Entity3 { get; set; } - #endregion DbSets - - #region Constructors - - partial void CustomInit(); - - #warning Default constructor not generated for Context2 since no default connection string was specified in the model - - /// - public Context2(string connectionString) : base(connectionString) - { - Configuration.LazyLoadingEnabled = true; - Configuration.ProxyCreationEnabled = true; - System.Data.Entity.Database.SetInitializer(new Context2DatabaseInitializer()); - CustomInit(); - } - - /// - public Context2(string connectionString, System.Data.Entity.Infrastructure.DbCompiledModel model) : base(connectionString, model) - { - Configuration.LazyLoadingEnabled = true; - Configuration.ProxyCreationEnabled = true; - System.Data.Entity.Database.SetInitializer(new Context2DatabaseInitializer()); - CustomInit(); - } - - /// - public Context2(System.Data.Common.DbConnection existingConnection, bool contextOwnsConnection) : base(existingConnection, contextOwnsConnection) - { - Configuration.LazyLoadingEnabled = true; - Configuration.ProxyCreationEnabled = true; - System.Data.Entity.Database.SetInitializer(new Context2DatabaseInitializer()); - CustomInit(); - } - - /// - public Context2(System.Data.Common.DbConnection existingConnection, System.Data.Entity.Infrastructure.DbCompiledModel model, bool contextOwnsConnection) : base(existingConnection, model, contextOwnsConnection) - { - Configuration.LazyLoadingEnabled = true; - Configuration.ProxyCreationEnabled = true; - System.Data.Entity.Database.SetInitializer(new Context2DatabaseInitializer()); - CustomInit(); - } - - /// - public Context2(System.Data.Entity.Infrastructure.DbCompiledModel model) : base(model) - { - Configuration.LazyLoadingEnabled = true; - Configuration.ProxyCreationEnabled = true; - System.Data.Entity.Database.SetInitializer(new Context2DatabaseInitializer()); - CustomInit(); - } - - /// - public Context2(System.Data.Entity.Core.Objects.ObjectContext objectContext, bool dbContextOwnsObjectContext) : base(objectContext, dbContextOwnsObjectContext) - { - Configuration.LazyLoadingEnabled = true; - Configuration.ProxyCreationEnabled = true; - System.Data.Entity.Database.SetInitializer(new Context2DatabaseInitializer()); - CustomInit(); - } - - #endregion Constructors - - partial void OnModelCreatingImpl(System.Data.Entity.DbModelBuilder modelBuilder); - partial void OnModelCreatedImpl(System.Data.Entity.DbModelBuilder modelBuilder); - - /// - protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - OnModelCreatingImpl(modelBuilder); - - modelBuilder.HasDefaultSchema("dbo"); - - modelBuilder.Entity().ToTable("Bases").HasKey(t => t.Id); - modelBuilder.Entity().Property(t => t.Id).IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); - - modelBuilder.Entity().ToTable("Entity1").HasKey(t => t.Id); - modelBuilder.Entity().Property(t => t.Id).IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); - modelBuilder.Entity().HasMany(x => x.Entity3).WithMany().Map(x => { x.ToTable("Entity1_x_Entity3"); x.MapLeftKey("Entity1_Id"); x.MapRightKey("Entity3_Id"); }); - - modelBuilder.Entity().ToTable("Entity2").HasKey(t => t.Id); - modelBuilder.Entity().Property(t => t.Id).IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); - modelBuilder.Entity().HasMany(x => x.Entity3).WithRequired().Map(x => x.MapKey("Entity2.Entity3_Id")); - - - OnModelCreatedImpl(modelBuilder); - } - } + /// + public partial class Context2 : DbContext + { + #region DbSets + public virtual System.Data.Entity.DbSet Bases { get; set; } + public virtual System.Data.Entity.DbSet Entity1 { get; set; } + public virtual System.Data.Entity.DbSet Entity2 { get; set; } + public virtual System.Data.Entity.DbSet Entity3 { get; set; } + #endregion DbSets + + #region Constructors + + partial void CustomInit(); + + #warning Default constructor not generated for Context2 since no default connection string was specified in the model + + /// + public Context2(string connectionString) : base(connectionString) + { + Configuration.LazyLoadingEnabled = true; + Configuration.ProxyCreationEnabled = true; + System.Data.Entity.Database.SetInitializer(new Context2DatabaseInitializer()); + CustomInit(); + } + + /// + public Context2(string connectionString, System.Data.Entity.Infrastructure.DbCompiledModel model) : base(connectionString, model) + { + Configuration.LazyLoadingEnabled = true; + Configuration.ProxyCreationEnabled = true; + System.Data.Entity.Database.SetInitializer(new Context2DatabaseInitializer()); + CustomInit(); + } + + /// + public Context2(System.Data.Common.DbConnection existingConnection, bool contextOwnsConnection) : base(existingConnection, contextOwnsConnection) + { + Configuration.LazyLoadingEnabled = true; + Configuration.ProxyCreationEnabled = true; + System.Data.Entity.Database.SetInitializer(new Context2DatabaseInitializer()); + CustomInit(); + } + + /// + public Context2(System.Data.Common.DbConnection existingConnection, System.Data.Entity.Infrastructure.DbCompiledModel model, bool contextOwnsConnection) : base(existingConnection, model, contextOwnsConnection) + { + Configuration.LazyLoadingEnabled = true; + Configuration.ProxyCreationEnabled = true; + System.Data.Entity.Database.SetInitializer(new Context2DatabaseInitializer()); + CustomInit(); + } + + /// + public Context2(System.Data.Entity.Infrastructure.DbCompiledModel model) : base(model) + { + Configuration.LazyLoadingEnabled = true; + Configuration.ProxyCreationEnabled = true; + System.Data.Entity.Database.SetInitializer(new Context2DatabaseInitializer()); + CustomInit(); + } + + /// + public Context2(System.Data.Entity.Core.Objects.ObjectContext objectContext, bool dbContextOwnsObjectContext) : base(objectContext, dbContextOwnsObjectContext) + { + Configuration.LazyLoadingEnabled = true; + Configuration.ProxyCreationEnabled = true; + System.Data.Entity.Database.SetInitializer(new Context2DatabaseInitializer()); + CustomInit(); + } + + #endregion Constructors + + partial void OnModelCreatingImpl(System.Data.Entity.DbModelBuilder modelBuilder); + partial void OnModelCreatedImpl(System.Data.Entity.DbModelBuilder modelBuilder); + + /// + protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + OnModelCreatingImpl(modelBuilder); + + modelBuilder.HasDefaultSchema("dbo"); + + modelBuilder.Entity().ToTable("Bases").HasKey(t => t.Id); + modelBuilder.Entity().Property(t => t.Id).IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); + + modelBuilder.Entity().ToTable("Entity1").HasKey(t => t.Id); + modelBuilder.Entity().Property(t => t.Id).IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); + modelBuilder.Entity().HasMany(x => x.Entity3).WithMany().Map(x => { x.ToTable("Entity1_x_Entity3"); x.MapLeftKey("Entity1_Id"); x.MapRightKey("Entity3_Id"); }); + + modelBuilder.Entity().ToTable("Entity2").HasKey(t => t.Id); + modelBuilder.Entity().Property(t => t.Id).IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); + modelBuilder.Entity().HasMany(x => x.Entity3).WithRequired().Map(x => x.MapKey("Entity2.Entity3_Id")); + + + OnModelCreatedImpl(modelBuilder); + } + } } diff --git a/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Context2DatabaseInitializer.generated.cs b/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Context2DatabaseInitializer.generated.cs index b0664985d..1922934dd 100644 --- a/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Context2DatabaseInitializer.generated.cs +++ b/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Context2DatabaseInitializer.generated.cs @@ -17,8 +17,8 @@ namespace MultiContext.Context2 { - /// - public partial class Context2DatabaseInitializer : MigrateDatabaseToLatestVersion - { - } + /// + public partial class Context2DatabaseInitializer : MigrateDatabaseToLatestVersion + { + } } diff --git a/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Context2DbMigrationConfiguration.generated.cs b/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Context2DbMigrationConfiguration.generated.cs index f604a9c84..367de6b4e 100644 --- a/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Context2DbMigrationConfiguration.generated.cs +++ b/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Context2DbMigrationConfiguration.generated.cs @@ -17,17 +17,17 @@ namespace MultiContext.Migrations { - /// - public sealed partial class Context2DbMigrationConfiguration : DbMigrationsConfiguration - { - partial void Init(); + /// + public sealed partial class Context2DbMigrationConfiguration : DbMigrationsConfiguration + { + partial void Init(); - /// - public Context2DbMigrationConfiguration() - { - AutomaticMigrationsEnabled = false; - AutomaticMigrationDataLossAllowed = false; - Init(); - } - } + /// + public Context2DbMigrationConfiguration() + { + AutomaticMigrationsEnabled = false; + AutomaticMigrationDataLossAllowed = false; + Init(); + } + } } diff --git a/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Placeholder.txt b/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Placeholder.txt deleted file mode 100644 index 5f282702b..000000000 --- a/src/Testing/Sandbox/Sandbox_EF6/Generated/Context/Placeholder.txt +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Base.generated.cs b/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Base.generated.cs index 580c4894d..314f7e917 100644 --- a/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Base.generated.cs +++ b/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Base.generated.cs @@ -24,29 +24,29 @@ namespace MultiContext.Context2 { - public partial class Base - { - partial void Init(); + public partial class Base + { + partial void Init(); - /// - /// Default constructor - /// - public Base() - { - Init(); - } + /// + /// Default constructor + /// + public Base() + { + Init(); + } - /************************************************************************* - * Properties - *************************************************************************/ + /************************************************************************* + * Properties + *************************************************************************/ - /// - /// Identity, Indexed, Required - /// - [Key] - [Required] - public int Id { get; protected set; } + /// + /// Identity, Indexed, Required + /// + [Key] + [Required] + public int Id { get; protected set; } - } + } } diff --git a/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Entity1.generated.cs b/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Entity1.generated.cs index d9774c34a..8b0340892 100644 --- a/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Entity1.generated.cs +++ b/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Entity1.generated.cs @@ -24,41 +24,41 @@ namespace MultiContext.Context2 { - public partial class Entity1 - { - partial void Init(); + public partial class Entity1 + { + partial void Init(); - /// - /// Default constructor - /// - public Entity1() - { - Entity3 = new System.Collections.Generic.HashSet(); + /// + /// Default constructor + /// + public Entity1() + { + Entity3 = new System.Collections.Generic.HashSet(); - Init(); - } + Init(); + } - /************************************************************************* - * Properties - *************************************************************************/ + /************************************************************************* + * Properties + *************************************************************************/ - /// - /// Identity, Required - /// - [Key] - [Required] - public int Id { get; protected set; } + /// + /// Identity, Required + /// + [Key] + [Required] + public int Id { get; protected set; } - public string Property1 { get; set; } + public string Property1 { get; set; } - public string Property2 { get; set; } + public string Property2 { get; set; } - /************************************************************************* - * Navigation properties - *************************************************************************/ + /************************************************************************* + * Navigation properties + *************************************************************************/ - public virtual ICollection Entity3 { get; protected set; } + public virtual ICollection Entity3 { get; protected set; } - } + } } diff --git a/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Entity2.generated.cs b/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Entity2.generated.cs index 40de19436..0661f7e72 100644 --- a/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Entity2.generated.cs +++ b/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Entity2.generated.cs @@ -24,43 +24,43 @@ namespace MultiContext.Context2 { - public partial class Entity2 - { - partial void Init(); + public partial class Entity2 + { + partial void Init(); - /// - /// Default constructor - /// - public Entity2() - { - Entity3 = new System.Collections.Generic.HashSet(); + /// + /// Default constructor + /// + public Entity2() + { + Entity3 = new System.Collections.Generic.HashSet(); - Init(); - } + Init(); + } - /************************************************************************* - * Properties - *************************************************************************/ + /************************************************************************* + * Properties + *************************************************************************/ - /// - /// Identity, Required - /// - [Key] - [Required] - public int Id { get; protected set; } + /// + /// Identity, Required + /// + [Key] + [Required] + public int Id { get; protected set; } - public string Property1 { get; set; } + public string Property1 { get; set; } - public string Property2 { get; set; } + public string Property2 { get; set; } - public string Property3 { get; set; } + public string Property3 { get; set; } - /************************************************************************* - * Navigation properties - *************************************************************************/ + /************************************************************************* + * Navigation properties + *************************************************************************/ - public virtual ICollection Entity3 { get; protected set; } + public virtual ICollection Entity3 { get; protected set; } - } + } } diff --git a/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Entity3.generated.cs b/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Entity3.generated.cs index 0fd1b143e..bef358793 100644 --- a/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Entity3.generated.cs +++ b/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Entity3.generated.cs @@ -24,58 +24,58 @@ namespace MultiContext.Context2 { - public partial class Entity3: global::MultiContext.Context2.Base - { - partial void Init(); + public partial class Entity3: global::MultiContext.Context2.Base + { + partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected Entity3(): base() - { - Init(); - } + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected Entity3(): base() + { + Init(); + } - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static Entity3 CreateEntity3Unsafe() - { - return new Entity3(); - } + /// + /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. + /// + public static Entity3 CreateEntity3Unsafe() + { + return new Entity3(); + } - /// - /// Public constructor with required data - /// - /// - public Entity3(global::MultiContext.Context2.Entity2 _entity21) - { - if (_entity21 == null) throw new ArgumentNullException(nameof(_entity21)); - _entity21.Entity3.Add(this); + /// + /// Public constructor with required data + /// + /// + public Entity3(global::MultiContext.Context2.Entity2 _entity21) + { + if (_entity21 == null) throw new ArgumentNullException(nameof(_entity21)); + _entity21.Entity3.Add(this); - Init(); - } + Init(); + } - /// - /// Static create function (for use in LINQ queries, etc.) - /// - /// - public static Entity3 Create(global::MultiContext.Context2.Entity2 _entity21) - { - return new Entity3(_entity21); - } + /// + /// Static create function (for use in LINQ queries, etc.) + /// + /// + public static Entity3 Create(global::MultiContext.Context2.Entity2 _entity21) + { + return new Entity3(_entity21); + } - /************************************************************************* - * Properties - *************************************************************************/ + /************************************************************************* + * Properties + *************************************************************************/ - public string Property1 { get; set; } + public string Property1 { get; set; } - /************************************************************************* - * Navigation properties - *************************************************************************/ + /************************************************************************* + * Navigation properties + *************************************************************************/ - } + } } diff --git a/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Placeholder.txt b/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Placeholder.txt deleted file mode 100644 index 5f282702b..000000000 --- a/src/Testing/Sandbox/Sandbox_EF6/Generated/Entities/Placeholder.txt +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/Testing/Sandbox/Sandbox_EF6/Sandbox_EF6.csproj b/src/Testing/Sandbox/Sandbox_EF6/Sandbox_EF6.csproj index 3c7fda7b6..634b5b465 100644 --- a/src/Testing/Sandbox/Sandbox_EF6/Sandbox_EF6.csproj +++ b/src/Testing/Sandbox/Sandbox_EF6/Sandbox_EF6.csproj @@ -84,8 +84,6 @@ TextTemplatingFileGenerator EFModel1.cs - -