diff --git a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core.UI/DisplayBinding/EDMDesignerViewContent.cs b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core.UI/DisplayBinding/EDMDesignerViewContent.cs index 784750c21f..7b4eba57f4 100644 --- a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core.UI/DisplayBinding/EDMDesignerViewContent.cs +++ b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core.UI/DisplayBinding/EDMDesignerViewContent.cs @@ -135,8 +135,7 @@ namespace ICSharpCode.Data.EDMDesigner.Core.UI.DisplayBinding public override void Save(OpenedFile file, Stream stream) { - Debug.Assert(file == this.PrimaryFile); - //Writer.Write(_designerCanvas.EDMView.EDM, EDMDesignerView.Writer.Write(_designerCanvas.EDMView)).Save(file.FileName); + EDMXIO.WriteXDocument(_edmView.EDM).Save(stream); } private EDMWizardWindow RunWizard(OpenedFile file) diff --git a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core.UI/UserControls/Relations/Association.xaml.cs b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core.UI/UserControls/Relations/Association.xaml.cs index 6499a1bf4e..65171f4998 100644 --- a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core.UI/UserControls/Relations/Association.xaml.cs +++ b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core.UI/UserControls/Relations/Association.xaml.cs @@ -62,11 +62,11 @@ namespace ICSharpCode.Data.EDMDesigner.Core.UI.UserControls.Relations public string FromCardinality { - get { return CardinalityStringConverter.CardinalityToSTring(CSDLAssociation.PropertyEnd1.Cardinality); } + get { return CardinalityStringConverter.CardinalityToString(CSDLAssociation.PropertyEnd1.Cardinality); } } public string ToCardinality { - get { return CardinalityStringConverter.CardinalityToSTring(CSDLAssociation.PropertyEnd2.Cardinality); } + get { return CardinalityStringConverter.CardinalityToString(CSDLAssociation.PropertyEnd2.Cardinality); } } protected override void OnAssociationCoordonatesChanged() diff --git a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/EDMObjects/Common/Cardinality.cs b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/EDMObjects/Common/Cardinality.cs index 901c53a9c2..222b5065cd 100644 --- a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/EDMObjects/Common/Cardinality.cs +++ b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/EDMObjects/Common/Cardinality.cs @@ -25,7 +25,7 @@ namespace ICSharpCode.Data.EDMDesigner.Core.EDMObjects.Common throw new NotImplementedException(); } - public static string CardinalityToSTring(Cardinality cardinality) + public static string CardinalityToString(Cardinality cardinality) { switch (cardinality) { diff --git a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/CSDLIO.cs b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/CSDLIO.cs index 996856c9ab..b474cb0b4b 100644 --- a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/CSDLIO.cs +++ b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/CSDLIO.cs @@ -6,6 +6,7 @@ using System; using System.Linq; using System.Xml.Linq; +using ICSharpCode.Data.Core.Common; using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.Common; using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.CSDL; using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.CSDL.Association; @@ -13,6 +14,7 @@ using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.CSDL.Common; using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.CSDL.Function; using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.CSDL.Property; using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.CSDL.Type; +using System.Collections.Generic; #endregion @@ -22,6 +24,8 @@ namespace ICSharpCode.Data.EDMDesigner.Core.IO { #region Methods + #region Read + public static CSDLContainer ReadXElement(XElement edmxRuntime) { XElement schemaElement = edmxRuntime.Element(XName.Get("ConceptualModels", edmxNamespace.NamespaceName)).Element(XName.Get("Schema", csdlNamespace.NamespaceName)); @@ -112,8 +116,6 @@ namespace ICSharpCode.Data.EDMDesigner.Core.IO return csdlContainer; } - #endregion - private static EntityType ReadCSDLEntityType(XElement schemaElement, XElement entityContainerElement, XElement entityTypeElement, CSDLContainer container, string typeName, EntityType baseType) { var entityType = new EntityType { Name = typeName, BaseType = baseType }; @@ -239,5 +241,203 @@ namespace ICSharpCode.Data.EDMDesigner.Core.IO return null; return values[0]; } + + #endregion + + #region Write + + public static XElement Write(CSDLContainer csdlContainer) + { + // Instantiate Schema + XElement schema = new XElement(csdlNamespace + "Schema", + new XAttribute("Namespace", csdlContainer.Namespace), + new XAttribute("Alias", csdlContainer.Alias), + new XAttribute(XNamespace.Xmlns + "annotation", csdlAnnotationNamespace.NamespaceName), + new XAttribute("xmlns", csdlNamespace.NamespaceName)); + + // EntityContainer + string entityContainerNamespace = string.Concat(csdlContainer.Namespace, "."); + XElement entityContainer = new XElement(csdlNamespace + "EntityContainer", new XAttribute("Name", csdlContainer.Name)); + schema.Add(entityContainer); + + // EntityContainer : EntitySets + foreach (EntityType entityType in csdlContainer.EntitySets) + { + XElement entitySetElement = new XElement(csdlNamespace + "EntitySet", + new XAttribute("Name", entityType.EntitySetName), + new XAttribute("EntityType", string.Concat(entityContainerNamespace, entityType.Name))); + //.AddAttribute(csdlCodeGenerationNamespace, "GetterAccess", entityType.EntitySetVisibility); + + entityContainer.Add(entitySetElement); + } + + // EntityContainer : AssociationSets + foreach (Association association in csdlContainer.Associations) + { + XElement associationSetElement = new XElement(csdlNamespace + "AssociationSet", + new XAttribute("Name", association.AssociationSetName), + new XAttribute("Association", string.Concat(entityContainerNamespace, association.Name))); + + associationSetElement.Add( + new XElement(csdlNamespace + "End", new XAttribute("Role", association.PropertyEnd1Role), new XAttribute("EntitySet", association.PropertyEnd1.EntityType.EntitySetName)), + new XElement(csdlNamespace + "End", new XAttribute("Role", association.PropertyEnd2Role), new XAttribute("EntitySet", association.PropertyEnd2.EntityType.EntitySetName))); + + entityContainer.AddElement(associationSetElement); + } + + // EntityContainer : FunctionImports + foreach (Function function in csdlContainer.Functions) + { + XElement functionElement = new XElement(csdlNamespace + "FunctionImport", + new XAttribute("Name", function.Name)) + .AddAttribute("EntitySet", function.EntityType == null ? null : function.EntityType.EntitySetName) + .AddAttribute("ReturnType", function.ReturnType); + + foreach (FunctionParameter functionParameter in function.Parameters) + { + functionElement.AddElement(new XElement(csdlNamespace + "Paramter", + new XAttribute("Name", functionParameter.Name), + new XAttribute("Type", functionParameter.Type)) + .AddAttribute("MaxLength", functionParameter.MaxLength) + .AddAttribute("Mode", functionParameter.Mode) + .AddAttribute("Precision", functionParameter.Precision) + .AddAttribute("Scale", functionParameter.Scale)); + } + + entityContainer.AddElement(functionElement); + } + + // ComplexTypes + foreach (ComplexType complexType in csdlContainer.ComplexTypes) + { + XElement complexTypeElement = new XElement(csdlNamespace + "ComplexType", + new XAttribute("Name", complexType.Name)); + //.AddAttribute(new XAttribute(csdlCodeGenerationNamespace + "TypeAccess", complexType.Visibility)); + + complexTypeElement.Add(WriteScalarProperties(complexType)); + complexTypeElement.Add(WriteComplexProperties(complexType, string.Concat(csdlContainer.Alias, "."))); + + schema.AddElement(complexTypeElement); + } + + // EntityTypes + foreach (EntityType entityType in csdlContainer.EntityTypes) + { + XElement entityTypeElement = new XElement(csdlNamespace + "EntityType") + .AddAttribute("Name", entityType.Name) + //.AddAttribute(csdlCodeGenerationNamespace, "TypeAccess", entityType.Visibility) + .AddAttribute("BaseType", entityType.BaseType == null ? null : string.Concat(entityContainerNamespace, entityType.BaseType.Name)) + .AddAttribute("Abstract", entityType.Abstract); + + if (entityType.SpecificKeys.Any()) + { + XElement keyElement = new XElement(csdlNamespace + "Key"); + + entityType.ScalarProperties.Where(sp => sp.IsKey).ForEach(scalarProperty => + { + keyElement.AddElement(new XElement(csdlNamespace + "PropertyRef") + .AddAttribute("Name", scalarProperty.Name)); + }); + + entityTypeElement.AddElement(keyElement); + } + + entityTypeElement.Add(WriteScalarProperties(entityType)); + entityTypeElement.Add(WriteComplexProperties(entityType, string.Concat(csdlContainer.Alias, "."))); + + // EntityType : NavigationProperties + entityType.NavigationProperties.Where(np => np.Generate).ForEach(navigationProperty => + { + entityTypeElement.AddElement(new XElement(csdlNamespace + "NavigationProperty") + .AddAttribute("Name", navigationProperty.Name) + .AddAttribute("Relationship", string.Concat(entityContainerNamespace, navigationProperty.Association.Name)) + .AddAttribute("FromRole", navigationProperty.Association.GetRoleName(navigationProperty)) + .AddAttribute("ToRole", navigationProperty.Association.GetRoleName(navigationProperty.Association.PropertiesEnd.First(role => role != navigationProperty)))); + //.AddAttribute(csdlCodeGenerationNamespace, "GetterAccess", navigationProperty.GetVisibility) + //.AddAttribute(csdlCodeGenerationNamespace, "SetterAccess", navigationProperty.SetVisibility)); + }); + + schema.AddElement(entityTypeElement); + } + + // Associations + foreach (Association association in csdlContainer.Associations) + { + XElement associationElement = new XElement(csdlNamespace + "Association") + .AddAttribute("Name", association.Name); + + associationElement.AddElement(new XElement(csdlNamespace + "End") + .AddAttribute("Role", association.PropertyEnd1Role) + .AddAttribute("Type", string.Concat(entityContainerNamespace, association.PropertyEnd1.EntityType.Name)) + .AddAttribute("Multiplicity", CardinalityStringConverter.CardinalityToString(association.PropertyEnd1.Cardinality))); + + associationElement.AddElement(new XElement(csdlNamespace + "End") + .AddAttribute("Role", association.PropertyEnd2Role) + .AddAttribute("Type", string.Concat(entityContainerNamespace, association.PropertyEnd2.EntityType.Name)) + .AddAttribute("Multiplicity", CardinalityStringConverter.CardinalityToString(association.PropertyEnd2.Cardinality))); + + if (association.PrincipalRole != null) + { + XElement referentialConstraintElement = new XElement(csdlNamespace + "ReferentialConstraint"); + + XElement principalElement = (new XElement(csdlNamespace + "Principal") + .AddAttribute("Role", association.PrincipalRole)); + + foreach (ScalarProperty propertyRef in association.PrincipalProperties) + principalElement.AddElement(new XElement(csdlNamespace + "PropertyRef").AddAttribute("Name", propertyRef.Name)); + + XElement dependentElement = (new XElement(csdlNamespace + "Dependent") + .AddAttribute("Role", association.DependentRole)); + + foreach (ScalarProperty propertyRef in association.DependentProperties) + dependentElement.AddElement(new XElement(csdlNamespace + "PropertyRef").AddAttribute("Name", propertyRef.Name)); + + referentialConstraintElement.AddElement(principalElement); + referentialConstraintElement.AddElement(dependentElement); + associationElement.AddElement(referentialConstraintElement); + } + + schema.AddElement(associationElement); + } + + return schema; + } + + private static IEnumerable WriteScalarProperties(TypeBase type) + { + foreach (ScalarProperty scalarProperty in type.ScalarProperties) + { + yield return new XElement(csdlNamespace + "Property") + .AddAttribute("Name", scalarProperty.Name) + .AddAttribute("Type", scalarProperty.Type) + .AddAttribute("Collation", scalarProperty.Collation) + .AddAttribute("ConcurrencyMode", scalarProperty.ConcurrencyMode) + .AddAttribute("DefaultValue", scalarProperty.DefaultValue) + .AddAttribute("FixedLength", scalarProperty.FixedLength) + //.AddAttribute(csdlCodeGenerationNamespace, "GetterAccess", scalarProperty.GetVisibility) + .AddAttribute("MaxLength", scalarProperty.MaxLength) + .AddAttribute("Nullable", scalarProperty.Nullable) + .AddAttribute("Precision", scalarProperty.Precision) + .AddAttribute("Scale", scalarProperty.Scale) + //.AddAttribute(csdlCodeGenerationNamespace, "SetterAccess", scalarProperty.SetVisibility) + .AddAttribute("Unicode", scalarProperty.Unicode); + } + } + + private static IEnumerable WriteComplexProperties(TypeBase type, string csdlAlias) + { + foreach (ComplexProperty complexProperty in type.ComplexProperties) + { + yield return new XElement(csdlNamespace + "Property") + .AddAttribute("Name", complexProperty.Name) + .AddAttribute("Type", string.Concat(csdlAlias, complexProperty.ComplexType.Name)) + .AddAttribute("Nullable", false); + //.AddAttribute(csdlCodeGenerationNamespace, "GetterAccess", complexProperty.GetVisibility); + } + } + + #endregion + + #endregion } } diff --git a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/DesignerIO.cs b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/DesignerIO.cs index 7350a6a14d..948cbb10f2 100644 --- a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/DesignerIO.cs +++ b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/DesignerIO.cs @@ -8,12 +8,14 @@ using System.Xml.Linq; using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.Designer; using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.Designer.CSDL.Type; using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.Designer.CSDL; +using ICSharpCode.Data.EDMDesigner.Core.EDMObjects; +using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.Designer.Common; #endregion namespace ICSharpCode.Data.EDMDesigner.Core.IO { - public class DesignerIO + public class DesignerIO : IO { public static void Read(EDMView edmView, XElement designerViewsXElement, Func createEntityDesignerFromUIType, Func createComplexDesignerFromUIType) { @@ -95,5 +97,38 @@ namespace ICSharpCode.Data.EDMDesigner.Core.IO return new XElement("DesignerViews", designerView); } + + public static XElement Write(EDM edm) + { + if (edm.DesignerProperties == null) + return null; + + XElement connectionElement = new XElement(edmxNamespace + "Connection"); + XElement designerInfoPropertyElement1 = new XElement(edmxNamespace + "DesignerInfoPropertyElement"); + connectionElement.Add(designerInfoPropertyElement1); + + foreach (DesignerProperty designerProperty in edm.DesignerProperties) + { + connectionElement.Add(new XElement(edmxNamespace + "DesignerProperty", + new XAttribute("Name", designerProperty.Name), + new XAttribute("Value", designerProperty.Value))); + } + + XElement optionsElement = new XElement(edmxNamespace + "Options"); + XElement designerInfoPropertyElement2 = new XElement(edmxNamespace + "DesignerInfoPropertyElement"); + optionsElement.Add(designerInfoPropertyElement2); + + foreach (DesignerProperty designerProperty in edm.DesignerProperties) + { + optionsElement.Add(new XElement(edmxNamespace + "DesignerProperty", + new XAttribute("Name", designerProperty.Name), + new XAttribute("Value", designerProperty.Value))); + } + + return new XElement(edmxNamespace + "Designer") + .AddElement(connectionElement) + .AddElement(optionsElement) + .AddElement(new XElement(edmxNamespace + "Diagrams", edm.EDMXDesignerDiagrams)); + } } } diff --git a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/EDMXIO.cs b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/EDMXIO.cs index d6fa099e47..c3aa739539 100644 --- a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/EDMXIO.cs +++ b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/EDMXIO.cs @@ -64,17 +64,32 @@ namespace ICSharpCode.Data.EDMDesigner.Core.IO return edm; } - public static XDocument WriteXDocument(XDocument ssdlXDocument, XDocument csdlXDocument, XDocument mslXDocument) + public static XDocument WriteXDocument(XDocument ssdlDocument, XDocument csdlDocument, XDocument mslDocument) + { + return WriteXDocument(ssdlDocument.Root, csdlDocument.Root, mslDocument.Root, null); + } + + public static XDocument WriteXDocument(XElement ssdlElement, XElement csdlElement, XElement mslElement, XElement designerElement) { return new XDocument(new XDeclaration("1.0", "utf-8", null), new XElement(edmxNamespace + "Edmx", new XAttribute("Version", "1.0"), new XAttribute(XNamespace.Xmlns + "edmx", edmxNamespace.NamespaceName), new XElement(edmxNamespace + "Runtime", new XElement(edmxNamespace + "StorageModels", - ssdlXDocument.Root), + ssdlElement), new XElement(edmxNamespace + "ConceptualModels", - csdlXDocument.Root), + csdlElement), new XElement(edmxNamespace + "Mappings", - mslXDocument.Root)))); + mslElement))).AddElement(designerElement)); + } + + public static XDocument WriteXDocument(EDM edm) + { + XElement ssdlElement = SSDLIO.WriteXElement(edm.SSDLContainer); + XElement csdlElement = CSDLIO.Write(edm.CSDLContainer); + XElement mslElement = MSLIO.Write(edm); + XElement designerElement = DesignerIO.Write(edm); + + return WriteXDocument(ssdlElement, csdlElement, mslElement, designerElement); } } } diff --git a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/IO.cs b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/IO.cs index 54dad01a3f..0c3eb18178 100644 --- a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/IO.cs +++ b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/IO.cs @@ -22,9 +22,10 @@ namespace ICSharpCode.Data.EDMDesigner.Core.IO protected static XNamespace csdlNamespace = "http://schemas.microsoft.com/ado/2008/09/edm"; protected static XNamespace csdlCodeGenerationNamespace = "http://schemas.microsoft.com/ado/2006/04/codegeneration"; + protected static XNamespace csdlAnnotationNamespace = "http://schemas.microsoft.com/ado/2009/02/edm/annotation"; protected static XNamespace mslNamespace = "http://schemas.microsoft.com/ado/2008/09/mapping/cs"; - + #endregion #region Helper functions diff --git a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/MSLIO.cs b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/MSLIO.cs index b1e5b749e1..668ecdd439 100644 --- a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/MSLIO.cs +++ b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/MSLIO.cs @@ -12,6 +12,9 @@ using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.MSL.Condition; using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.MSL.CUDFunction; using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.MSL.EntityType; using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.SSDL; +using ICSharpCode.Data.EDMDesigner.Core.EDMObjects; +using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.CSDL.Association; +using ICSharpCode.Data.EDMDesigner.Core.EDMObjects.CSDL.Function; #endregion @@ -20,7 +23,9 @@ namespace ICSharpCode.Data.EDMDesigner.Core.IO public class MSLIO : IO { #region Methods - + + #region Read + public static XDocument GenerateTypeMapping(XDocument mslDocument) { XElement mappingElement = mslDocument.Element(XName.Get("Mapping", mslNamespace.NamespaceName)); @@ -256,5 +261,303 @@ namespace ICSharpCode.Data.EDMDesigner.Core.IO } #endregion + + #region Write + + public static XElement Write(EDM edm) + { + CSDLContainer csdlContainer = edm.CSDLContainer; + string entityContainerNamespace = string.Concat(csdlContainer.Namespace, "."); + + // Instantiate Mapping + XElement mapping = new XElement(mslNamespace + "Mapping", + new XAttribute("Space", "C-S")); + + // EntityContainerMapping + XElement entityContainerMapping = new XElement(mslNamespace + "EntityContainerMapping", + new XAttribute("StorageEntityContainer", edm.SSDLContainer.Name), + new XAttribute("CdmEntityContainer", csdlContainer.Name)); + + foreach (EntityType entitySet in csdlContainer.EntitySets) + { + IEnumerable entityTypes = csdlContainer.EntityTypes.Where(entityType => entityType.EntitySetName == entitySet.EntitySetName); + + // EntityContainerMapping : EntitySetMapping + XElement entitySetMappingElement = new XElement(mslNamespace + "EntitySetMapping", + new XAttribute("Name", entitySet.Name)); + + // EntityContainerMapping : EntitySetMapping : EntityTypeMapping + foreach (EntityType entityType in entityTypes) + { + XElement entityTypeMappingElement = new XElement(mslNamespace + "EntityTypeMapping", + new XAttribute("TypeName", string.Format("IsTypeOf({0}{1})", entityContainerNamespace, entityType.Name))); + + // EntityContainerMapping : EntitySetMapping : EntityTypeMapping : MappingFragment + foreach (EDMObjects.SSDL.EntityType.EntityType table in entityType.Mapping.MappedSSDLTables) + { + XElement mappingFragmentElement = new XElement(mslNamespace + "MappingFragment", + new XAttribute("StoreEntitySet", table.EntitySetName)); + + IEnumerable scalarMappings = entityType.Mapping.GetSpecificMappingForTable(table); + + foreach (PropertyMapping scalarMapping in scalarMappings) + { + mappingFragmentElement.AddElement(new XElement(mslNamespace + "ScalarProperty", + new XAttribute("Name", scalarMapping.Property.Name), + new XAttribute("ColumnName", scalarMapping.Column.Name))); + } + + mappingFragmentElement.Add(MappingComplexProperties(entityType, entityType.Mapping, table, entityContainerNamespace)); + + IEnumerable conditionMappings = entityType.Mapping.ConditionsMapping.Where(condition => condition.Table == table); + + foreach (ConditionMapping conditionMapping in conditionMappings) + { + XElement conditionElement = new XElement(mslNamespace + "Condition"); + + if (conditionMapping is ColumnConditionMapping) + conditionElement.AddAttribute("ColumnName", (conditionMapping as ColumnConditionMapping).Column.Name); + else if (conditionMapping is PropertyConditionMapping) + conditionElement.AddAttribute("Name", (conditionMapping as PropertyConditionMapping).CSDLProperty.Name); + + mappingFragmentElement.Add(conditionElement.AddMappingConditionAttribute(conditionMapping)); + } + + entityTypeMappingElement.Add(mappingFragmentElement); + } + + entitySetMappingElement.Add(entityTypeMappingElement); + } + + // EntityContainerMapping : EntitySetMapping : CUDFunctionMapping + foreach (EntityType entityType in entityTypes) + { + entitySetMappingElement.Add(CUDFunctionMapping(entityType, entityContainerNamespace, string.Concat(edm.SSDLContainer.Namespace, "."))); + } + + entityContainerMapping.Add(entitySetMappingElement); + } + + // EntityContainerMapping : AssociationSetMappings + IEnumerable associations = csdlContainer.Associations.Where(association => association.Mapping.SSDLTableMapped != null); + + foreach (Association association in associations) + { + XElement associationSetMappingElement = new XElement(mslNamespace + "AssociationSetMapping", + new XAttribute("Name", association.AssociationSetName), + new XAttribute("TypeName", string.Concat(entityContainerNamespace, association.Name)), + new XAttribute("StoreEntitySet", association.Mapping.SSDLTableMapped.Name)); + + XElement endPropertyElement1 = new XElement(mslNamespace + "EndProperty", + new XAttribute("Name", association.PropertyEnd1Role)); + + foreach (PropertyMapping navigationPropertyMapping in association.PropertyEnd1.Mapping) + { + endPropertyElement1.AddElement(new XElement(mslNamespace + "ScalarProperty", + new XAttribute("Name", navigationPropertyMapping.Property.Name), + new XAttribute("ColumnName", navigationPropertyMapping.Column.Name))); + } + + XElement endPropertyElement2 = new XElement(mslNamespace + "EndProperty", + new XAttribute("Name", association.PropertyEnd2Role)); + + foreach (PropertyMapping navigationPropertyMapping in association.PropertyEnd2.Mapping) + { + endPropertyElement2.AddElement(new XElement(mslNamespace + "ScalarProperty", + new XAttribute("Name", navigationPropertyMapping.Property.Name), + new XAttribute("ColumnName", navigationPropertyMapping.Column.Name))); + } + + associationSetMappingElement.Add(endPropertyElement1); + associationSetMappingElement.Add(endPropertyElement2); + + entityContainerMapping.Add(associationSetMappingElement); + } + + // EntityContainerMapping : Conditions + foreach (Function function in csdlContainer.Functions) + { + entityContainerMapping.Add(new XElement(mslNamespace + "FunctionImportMapping", + new XAttribute("FunctionImportName", function.Name), + new XAttribute("FunctionName", string.Format("{0}.{1}", edm.SSDLContainer.Namespace, function.SSDLFunction.Name)))); + } + + return mapping.AddElement(entityContainerMapping); + } + + private static IEnumerable MappingComplexProperties(TypeBase type, MappingBase mapping, EDMObjects.SSDL.EntityType.EntityType table, string entityContainerNamespace) + { + foreach (ComplexProperty complexProperty in type.AllComplexProperties) + { + ComplexPropertyMapping complexPropertyMapping = mapping.GetEntityTypeSpecificComplexPropertyMapping(complexProperty); + + if (complexPropertyMapping != null) + { + XElement complexPropertyElement = new XElement(mslNamespace + "ComplexProperty", + new XAttribute("Name", complexProperty.Name)); + + IEnumerable scalarMappings = complexPropertyMapping.GetSpecificMappingForTable(table); + + foreach (PropertyMapping scalarMapping in scalarMappings) + { + complexPropertyElement.AddElement(new XElement(mslNamespace + "ScalarProperty", + new XAttribute("Name", scalarMapping.Property.Name), + new XAttribute("ColumnName", scalarMapping.Column.Name))); + } + + foreach (ComplexProperty subComplexProperty in complexProperty.ComplexType.ComplexProperties) + { + complexPropertyElement.Add(MappingComplexProperties(complexProperty.ComplexType, complexPropertyMapping, table, entityContainerNamespace)); + } + + yield return complexPropertyElement; + } + } + } + + private static XElement MappingColumnCondition(ColumnConditionMapping condition) + { + return new XElement(mslNamespace + "Condition", new XAttribute("ColumnName", condition.Column.Name)).AddMappingConditionAttribute(condition); + } + + private static XElement CUDFunctionMapping(EntityType entityType, string entityContainerNamespace, string storeContainerNamespace) + { + EntityTypeMapping mapping = entityType.Mapping; + + if (mapping.InsertFunctionMapping == null || mapping.UpdateFunctionMapping == null || mapping.DeleteFunctionMapping == null) + return null; + + XElement modificationFunctionMapping = new XElement(mslNamespace + "ModificationFunctionMapping"); + + var insertFunction = mapping.InsertFunctionMapping; + + if (insertFunction != null) + { + XElement insertFunctionElement = new XElement(mslNamespace + "InsertFunction", + new XAttribute("FunctionName", string.Concat(storeContainerNamespace, insertFunction.SSDLFunction.Name))); + + insertFunctionElement.Add(CUDFunctionMappingAssociation(insertFunction)); + insertFunctionElement.Add(CUDFunctionMappingParameters(insertFunction)); + insertFunctionElement.Add(CUDFunctionMappingResults(insertFunction)); + + modificationFunctionMapping.AddElement(insertFunctionElement); + } + + var updateFunction = mapping.UpdateFunctionMapping; + + if (updateFunction != null) + { + XElement updateFunctionElement = new XElement(mslNamespace + "UpdateFunction", + new XAttribute("FunctionName", string.Concat(storeContainerNamespace, updateFunction.SSDLFunction.Name))); + + updateFunctionElement.Add(CUDFunctionMappingAssociation(updateFunction)); + updateFunctionElement.Add(CUDFunctionMappingParameters(updateFunction)); + updateFunctionElement.Add(CUDFunctionMappingResults(updateFunction)); + + modificationFunctionMapping.AddElement(updateFunctionElement); + } + + var deleteFunction = mapping.DeleteFunctionMapping; + + if (deleteFunction != null) + { + XElement deleteFunctionElement = new XElement(mslNamespace + "DeleteFunction", + new XAttribute("FunctionName", string.Concat(storeContainerNamespace, deleteFunction.SSDLFunction.Name))); + + deleteFunctionElement.Add(CUDFunctionMappingAssociation(deleteFunction)); + deleteFunctionElement.Add(CUDFunctionMappingParameters(deleteFunction)); + deleteFunctionElement.Add(CUDFunctionMappingResults(deleteFunction)); + + modificationFunctionMapping.AddElement(deleteFunctionElement); + } + + return new XElement(mslNamespace + "EntityTypeMapping", + new XAttribute("TypeName", string.Concat(entityContainerNamespace, entityType.Name)), + modificationFunctionMapping); + } + + private static IEnumerable CUDFunctionMappingAssociation(CUDFunctionMapping functionMapping) + { + foreach (CUDFunctionAssociationMapping cudFunctionAssiociation in functionMapping.AssociationMappings) + { + XElement associationEndElement = new XElement(mslNamespace + "AssociationEnd", + new XAttribute("AssociationSet", cudFunctionAssiociation.Association.AssociationSetName), + new XAttribute("From", cudFunctionAssiociation.FromRole), + new XAttribute("To", cudFunctionAssiociation.ToRole)); + + associationEndElement.Add(CUDFunctionMappingScalarPropertiesParameters(cudFunctionAssiociation.AssociationPropertiesMapping)); + + yield return associationEndElement; + } + } + + private static IEnumerable CUDFunctionMappingParameters(CUDFunctionMapping functionMapping) + { + return CUDFunctionMappingParameters(functionMapping.ParametersMapping); + } + + private static IEnumerable CUDFunctionMappingParameters(EntityTypeCUDFunctionParametersMapping cudFunctionParameters) + { + List complexProperties = new List(); + + foreach (var complexParameter in cudFunctionParameters.ComplexPropertiesMapping) + { + XElement complexProperty = new XElement(mslNamespace + "Complexproperty", + new XAttribute("Name", complexParameter.Key.Name)); + complexProperty.Add(CUDFunctionMappingParameters(complexParameter.Value)); + } + + return CUDFunctionMappingScalarPropertiesParameters(cudFunctionParameters).Union(complexProperties); + } + + private static IEnumerable CUDFunctionMappingScalarPropertiesParameters(CUDFunctionParametersMapping cudFunctionParameters) + { + foreach (var parameter in cudFunctionParameters) + { + yield return new XElement(mslNamespace + "ScalarProperty", + new XAttribute("Name", parameter.Key.Name), + new XAttribute("ParameterName", parameter.Value.SSDLFunctionParameter.Name)) + .AddAttribute(null, "Version", parameter.Value.Version); + } + } + + private static IEnumerable CUDFunctionMappingResults(CUDFunctionMapping functionMapping) + { + foreach (var result in functionMapping.ResultsMapping) + { + yield return new XElement(mslNamespace + "ResultBinding", + new XAttribute("Name", result.Key.Name), + new XAttribute("ColumnName", result.Value)); + } + } + + #endregion + + #endregion + } + + #region Extension methods + + internal static class MSLIOHelpers + { + public static XElement AddMappingConditionAttribute(this XElement element, ConditionMapping conditionMapping) + { + switch (conditionMapping.Operator) + { + case ConditionOperator.IsNotNull: + element.Add(new XAttribute("IsNull", false)); + break; + case ConditionOperator.IsNull: + element.Add(new XAttribute("IsNull", true)); + break; + case ConditionOperator.Equals: + element.Add(new XAttribute("Value", conditionMapping.Value)); + break; + } + + return element; + } } + + #endregion } diff --git a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/SSDLIO.cs b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/SSDLIO.cs index 679a4b6bb0..ac4fb9b8ff 100644 --- a/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/SSDLIO.cs +++ b/src/AddIns/DisplayBindings/Data/ICSharpCode.Data.EDMDesigner.Core/IO/SSDLIO.cs @@ -67,7 +67,7 @@ namespace ICSharpCode.Data.EDMDesigner.Core.IO string role2Name = association.Role2.Name; - // If the assocation end properties are the same properties + // If the association end properties are the same properties if (association.Role1.Name == association.Role2.Name && association.Role1.Type.Name == association.Role2.Type.Name) role2Name += "1"; @@ -120,17 +120,17 @@ namespace ICSharpCode.Data.EDMDesigner.Core.IO { string role2Name = association.Role2.Name; - // If the assocation end properties are the same properties + // If the association end properties are the same properties if (association.Role1.Name == association.Role2.Name && association.Role1.Type.Name == association.Role2.Type.Name) role2Name += "1"; XElement associationElement = new XElement(ssdlNamespace + "Association", new XAttribute("Name", association.Name), - new XElement(ssdlNamespace + "End", new XAttribute("Role", association.Role1.Name), new XAttribute("Type", string.Concat(entityContainerNamespace, association.Role1.Type.Name)), new XAttribute("Multiplicity", CardinalityStringConverter.CardinalityToSTring(association.Role1.Cardinality))), - new XElement(ssdlNamespace + "End", new XAttribute("Role", role2Name), new XAttribute("Type", string.Concat(entityContainerNamespace, association.Role2.Type.Name)), new XAttribute("Multiplicity", CardinalityStringConverter.CardinalityToSTring(association.Role2.Cardinality)))); + new XElement(ssdlNamespace + "End", new XAttribute("Role", association.Role1.Name), new XAttribute("Type", string.Concat(entityContainerNamespace, association.Role1.Type.Name)), new XAttribute("Multiplicity", CardinalityStringConverter.CardinalityToString(association.Role1.Cardinality))), + new XElement(ssdlNamespace + "End", new XAttribute("Role", role2Name), new XAttribute("Type", string.Concat(entityContainerNamespace, association.Role2.Type.Name)), new XAttribute("Multiplicity", CardinalityStringConverter.CardinalityToString(association.Role2.Cardinality)))); string dependentRoleName = association.DependantRole.Name; - // If the assocation end properties are the same properties + // If the association end properties are the same properties if (association.PrincipalRole.Name == association.DependantRole.Name && association.PrincipalRole.Type.Name == association.DependantRole.Type.Name) dependentRoleName += "1"; @@ -260,13 +260,42 @@ namespace ICSharpCode.Data.EDMDesigner.Core.IO { isPrincipal = true; association.PrincipalRole = role; - role.Properties = role.Type.Properties.Where(p => p.Name == principalElement.Element(XName.Get("PropertyRef", ssdlNamespace.NamespaceName)).Attribute("Name").Value).ToEventedObservableCollection(); + + EventedObservableCollection properties = new EventedObservableCollection(); + + foreach (XElement element in principalElement.Elements(XName.Get("PropertyRef", ssdlNamespace.NamespaceName))) + { + foreach (Property property in role.Type.Properties) + { + if (property.Name == element.Attribute("Name").Value) + properties.Add(property); + } + } + + role.Properties = properties; + + //role.Properties = role.Type.Properties.Where(p => p.Name == principalElement.Element(XName.Get("PropertyRef", ssdlNamespace.NamespaceName)).Attribute("Name").Value).ToEventedObservableCollection(); } else { isPrincipal = false; association.DependantRole = role; - role.Properties = role.Type.Properties.Where(p => p.Name == referentialConstraintElement.Element(XName.Get("Dependent", ssdlNamespace.NamespaceName)).Element(XName.Get("PropertyRef", ssdlNamespace.NamespaceName)).Attribute("Name").Value).ToEventedObservableCollection(); + + EventedObservableCollection properties = new EventedObservableCollection(); + XElement dependentElement = referentialConstraintElement.Element(XName.Get("Dependent", ssdlNamespace.NamespaceName)); + + foreach (XElement element in dependentElement.Elements(XName.Get("PropertyRef", ssdlNamespace.NamespaceName))) + { + foreach (Property property in role.Type.Properties) + { + if (property.Name == element.Attribute("Name").Value) + properties.Add(property); + } + } + + role.Properties = properties; + + //role.Properties = role.Type.Properties.Where(p => p.Name == referentialConstraintElement.Element(XName.Get("Dependent", ssdlNamespace.NamespaceName)).Element(XName.Get("PropertyRef", ssdlNamespace.NamespaceName)).Attribute("Name").Value).ToEventedObservableCollection(); } } if (isPrincipal)