<# // You can use this text template to customize object layer code generation for // applications that use the Entity Framework. The template generates code based on an .edmx file. // Before using this template, note the following: // // *The name of the text template file will determine the name of the code file it generates. // For example, if the text template is named TextTemplate.tt, the generated file will be named // TextTemplate.vb or TextTemplate.cs. // *The Custom Tool property of the targeted .edmx file must be empty. For more information, // see .edmx File Properties (http://go.microsoft.com/fwlink/?LinkId=139299). // *The SourceCsdlPath initialization below must be set to one of the following: // 1) the path of the targeted .edmx or .csdl file // 2) the path of the targeted .edmx or .csdl file relative to the template path // // For more detailed information about using this template, see // How to: Customize Object Layer Code Generation (http://go.microsoft.com/fwlink/?LinkId=139297). // For general information about text templates, see // Generating Artifacts by Using Text Templates (http://go.microsoft.com/fwlink/?LinkId=139298) #> <#@ template language="C#" debug="false" hostspecific="true"#> <#@ include file="EF.Utility.CS.ttinclude"#><#@ output extension=".cs"#><# UserSettings userSettings = new UserSettings { SourceCsdlPath = @"YOUR_EDMX_FILE.edmx", ReferenceCsdlPaths = new string[] {}, FullyQualifySystemTypes = true, CreateContextAddToMethods = true, CamelCaseFields = false, }; ApplyUserSettings(userSettings); if(Errors.HasErrors) { return String.Empty; } MetadataLoader loader = new MetadataLoader(this); MetadataTools ef = new MetadataTools(this); CodeRegion region = new CodeRegion(this); CodeGenerationTools code = new CodeGenerationTools(this){FullyQualifySystemTypes = userSettings.FullyQualifySystemTypes, CamelCaseFields = userSettings.CamelCaseFields}; ItemCollection = loader.CreateEdmItemCollection(SourceCsdlPath, ReferenceCsdlPaths.ToArray()); ModelNamespace = loader.GetModelNamespace(SourceCsdlPath); string namespaceName = code.VsNamespaceSuggestion() ?? GetObjectNamespace(ModelNamespace); UpdateObjectNamespaceMap(namespaceName); #> //------------------------------------------------------------------------------ // // <#=GetResourceString("Template_GeneratedCodeCommentLine1")#> // // <#=GetResourceString("Template_GeneratedCodeCommentLine2")#> // <#=GetResourceString("Template_GeneratedCodeCommentLine3")#> // //------------------------------------------------------------------------------ using System; using System.Data.Objects; using System.Data.Objects.DataClasses; using System.Data.EntityClient; using System.ComponentModel; using System.Xml.Serialization; using System.Runtime.Serialization; [assembly: EdmSchemaAttribute()] <# //////// //////// Write Relationship Attributes //////// region.Begin(GetResourceString("Template_RegionRelationships")); bool first = true; foreach (AssociationType association in GetSourceSchemaTypes()) { if (first) { WriteLine(string.Empty); first = false; } #> [assembly: EdmRelationshipAttribute("<#=association.NamespaceName#>", "<#=association.Name#>", "<#=EndName(association, 0)#>", <#=EndMultiplicity(association, 0)#>, typeof(<#=EscapeEndTypeName(association, 0, code)#>), "<#=EndName(association, 1)#>", <#=EndMultiplicity(association, 1)#>, typeof(<#=EscapeEndTypeName(association, 1, code)#>)<#=code.StringBefore(", ", association.IsForeignKey ? "true" : null)#>)] <# } region.End(); if (!String.IsNullOrEmpty(namespaceName)) { #> namespace <#=namespaceName#> { <# PushIndent(CodeRegion.GetIndent(1)); } //////// //////// Write EntityContainer and ObjectContext classes. //////// region.Begin(GetResourceString("Template_RegionContexts")); foreach (EntityContainer container in GetSourceSchemaTypes()) { #> /// /// <#=SummaryComment(container)#> /// <#=LongDescriptionCommentElement(container, region.CurrentIndentLevel)#> [global::System.CodeDom.Compiler.GeneratedCode("EdmxTool", "1.0.0.0")] <#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : ObjectContext { #region <#=GetResourceString("Template_RegionConstructors")#> /// /// <#=String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_ContextDefaultCtorComment"), container.Name, container.Name)#> /// public <#=code.Escape(container)#>() : base("name=<#=container.Name#>", "<#=container.Name#>") { <# WriteLazyLoadingEnabled(container); #> OnContextCreated(); } /// /// <#=String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_ContextCommonCtorComment"), container.Name)#> /// public <#=code.Escape(container)#>(string connectionString) : base(connectionString, "<#=container.Name#>") { <# WriteLazyLoadingEnabled(container); #> OnContextCreated(); } /// /// <#=String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_ContextCommonCtorComment"), container.Name)#> /// public <#=code.Escape(container)#>(EntityConnection connection) : base(connection, "<#=container.Name#>") { <# WriteLazyLoadingEnabled(container); #> OnContextCreated(); } #endregion #region <#=GetResourceString("Template_RegionPartialMethods")#> partial void OnContextCreated(); #endregion <# //////// //////// Write EntityContainer and ObjectContext ObjectSet properties. //////// region.Begin(GetResourceString("Template_RegionObjectSetProperties")); foreach (EntitySet set in container.BaseEntitySets.OfType()) { VerifyEntityTypeAndSetAccessibilityCompatability(set); #> /// /// <#=SummaryComment(set)#> /// <#=LongDescriptionCommentElement(set, region.CurrentIndentLevel)#> <#=code.SpaceAfter(NewModifier(set))#><#=Accessibility.ForReadOnlyProperty(set)#> ObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>> <#=code.Escape(set)#> { get { if ((<#=code.FieldName(set)#> == null)) { <#=code.FieldName(set)#> = base.CreateObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>>("<#=set.Name#>"); } return <#=code.FieldName(set)#>; } } private ObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>> <#=code.FieldName(set)#>; <# } region.End(); //////// //////// Write EntityContainer and ObjectContext AddTo methods. //////// //////// AddTo methods are no longer necessary since the EntitySet properties return //////// an ObjectSet object, which has already has an Add method. //////// //////// AddTo methods are generated here for backwards compatibility reasons only. //////// Set the CreateContextAddToMethods property of the UserSettings object to false //////// to turn off generation of the AddTo methods. //////// region.Begin(GetResourceString("Template_RegionAddToMethods")); IEnumerable addToMethods = CreateContextAddToMethods.Value ? container.BaseEntitySets.OfType() : Enumerable.Empty(); foreach (EntitySet set in addToMethods) { string parameterName = code.Escape(FixParameterName(set.ElementType.Name, code)); #> /// /// <#=String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_GenCommentAddToMethodCs"), set.Name)#> /// <#=Accessibility.ForType(set.ElementType)#> void AddTo<#=set.Name#>(<#=MultiSchemaEscape(set.ElementType, code)#> <#=parameterName#>) { base.AddObject("<#=set.Name#>", <#=parameterName#>); } <# } region.End(); //////// //////// Write EntityContainer and ObjectContext Function Import methods. //////// region.Begin(GetResourceString("Template_RegionFunctionImports")); foreach (EdmFunction edmFunction in container.FunctionImports) { IEnumerable parameters = FunctionImportParameter.Create(edmFunction.Parameters, code, ef); string paramList = string.Join(", ", parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray()); TypeUsage returnType = edmFunction.ReturnParameter == null ? null : ef.GetElementType(edmFunction.ReturnParameter.TypeUsage); #> /// /// <#=SummaryComment(edmFunction)#> /// <#=LongDescriptionCommentElement(edmFunction, region.CurrentIndentLevel)#><#=ParameterComments(parameters.Select(p => new Tuple(p.RawFunctionParameterName, SummaryComment(p.Source))), region.CurrentIndentLevel)#> <#=code.SpaceAfter(NewModifier(edmFunction))#><#=Accessibility.ForMethod(edmFunction)#> <#=returnType == null ? "int" : "ObjectResult<" + MultiSchemaEscape(returnType, code) + ">"#> <#=code.Escape(edmFunction)#>(<#=paramList#>) { <# foreach (FunctionImportParameter parameter in parameters) { if (!parameter.NeedsLocalVariable) continue; #> ObjectParameter <#=parameter.LocalVariableName#>; if (<#=parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null"#>) { <#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", <#=parameter.FunctionParameterName#>); } else { <#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", typeof(<#=parameter.RawClrTypeName#>)); } <# } #> return base.ExecuteFunction<#=returnType == null ? "" : "<" + MultiSchemaEscape(returnType, code) + ">"#>("<#=edmFunction.Name#>"<#=code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))#>); } <# if(returnType != null && returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType) { #> /// /// <#=SummaryComment(edmFunction)#> /// <#=LongDescriptionCommentElement(edmFunction, region.CurrentIndentLevel)#> /// <#=ParameterComments(parameters.Select(p => new Tuple(p.RawFunctionParameterName, SummaryComment(p.Source))), region.CurrentIndentLevel)#> <#=code.SpaceAfter(NewModifier(edmFunction))#><#=Accessibility.ForMethod(edmFunction)#> <#=returnType == null ? "int" : "ObjectResult<" + MultiSchemaEscape(returnType, code) + ">"#> <#=code.Escape(edmFunction)#>(<#=code.StringAfter(paramList, ", ")#>MergeOption mergeOption) { <# foreach (FunctionImportParameter parameter in parameters) { if (!parameter.NeedsLocalVariable) continue; #> ObjectParameter <#=parameter.LocalVariableName#>; if (<#=parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null"#>) { <#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", <#=parameter.FunctionParameterName#>); } else { <#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", typeof(<#=parameter.RawClrTypeName#>)); } <# } #> return base.<#=returnType == null ? "ExecuteFunction" : "ExecuteFunction<" + MultiSchemaEscape(returnType, code) + ">"#>("<#=edmFunction.Name#>", mergeOption<#=code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))#>); } <# } } region.End(); #> } <# } region.End(); #> <# //////// //////// Write EntityType classes. //////// region.Begin(GetResourceString("Template_RegionEntities")); foreach (EntityType entity in GetSourceSchemaTypes().OrderBy(e => e.Name)) { #> /// /// <#=SummaryComment(entity)#> /// <#=LongDescriptionCommentElement(entity, region.CurrentIndentLevel)#> [EdmEntityTypeAttribute(NamespaceName="<#=entity.NamespaceName#>", Name="<#=entity.Name#>")] [Serializable()] [DataContractAttribute(IsReference=true)] [global::System.CodeDom.Compiler.GeneratedCode("EdmxTool", "1.0.0.0")] <# foreach (EntityType subType in ItemCollection.GetItems().Where(b => b.BaseType == entity)) { #> [KnownTypeAttribute(typeof(<#=MultiSchemaEscape(subType, code)#>))] <# } #> <#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class <#=code.Escape(entity)#> : <#=BaseTypeName(entity, code)#> { <# if (!entity.Abstract) { WriteFactoryMethod(entity, code); } region.Begin(GetResourceString("Template_RegionPrimitiveProperties")); foreach (EdmProperty property in entity.Properties.Where(p => p.DeclaringType == entity && p.TypeUsage.EdmType is PrimitiveType)) { VerifyGetterAndSetterAccessibilityCompatability(property); WritePrimitiveTypeProperty(property, code); } region.End(); region.Begin(GetResourceString("Template_RegionComplexProperties")); foreach (EdmProperty property in entity.Properties.Where(p => p.DeclaringType == entity && p.TypeUsage.EdmType is ComplexType)) { VerifyGetterAndSetterAccessibilityCompatability(property); WriteComplexTypeProperty(property, code); } region.End(); #> <# //////// //////// Write Navigation Properties. //////// region.Begin(GetResourceString("Template_RegionNavigationProperties")); foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(n => n.DeclaringType == entity)) { VerifyGetterAndSetterAccessibilityCompatability(navProperty); #> /// /// <#=SummaryComment(navProperty)#> /// <#=LongDescriptionCommentElement(navProperty, region.CurrentIndentLevel)#> [XmlIgnoreAttribute()] [SoapIgnoreAttribute()] [DataMemberAttribute()] [EdmRelationshipNavigationPropertyAttribute("<#=navProperty.RelationshipType.NamespaceName#>", "<#=navProperty.RelationshipType.Name#>", "<#=navProperty.ToEndMember.Name#>")] <# if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) { #> <#=code.SpaceAfter(NewModifier(navProperty))#><#=Accessibility.ForProperty(navProperty)#> EntityCollection<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>> <#=code.Escape(navProperty)#> { <#=code.SpaceAfter(Accessibility.ForGetter(navProperty))#>get { return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>"); } <#=code.SpaceAfter(Accessibility.ForSetter(navProperty))#>set { if ((value != null)) { ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedCollection<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>", value); } } } <# } else { #> <#=code.SpaceAfter(NewModifier(navProperty))#><#=Accessibility.ForProperty(navProperty)#> <#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#> <#=code.Escape(navProperty)#> { <#=code.SpaceAfter(Accessibility.ForGetter(navProperty))#>get { return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>").Value; } <#=code.SpaceAfter(Accessibility.ForSetter(navProperty))#>set { ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>").Value = value; } } <# string refPropertyName = navProperty.Name + "Reference"; if (entity.Members.Any(m => m.Name == refPropertyName)) { // 6017 is the same error number that EntityClassGenerator uses. Errors.Add(new System.CodeDom.Compiler.CompilerError(SourceCsdlPath, -1, -1, "6017", String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_ConflictingGeneratedNavPropName"), navProperty.Name, entity.FullName, refPropertyName))); } #> /// /// <#=SummaryComment(navProperty)#> /// <#=LongDescriptionCommentElement(navProperty, region.CurrentIndentLevel)#> [BrowsableAttribute(false)] [DataMemberAttribute()] <#=Accessibility.ForProperty(navProperty)#> EntityReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>> <#=refPropertyName#> { <#=code.SpaceAfter(Accessibility.ForGetter(navProperty))#>get { return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>"); } <#=code.SpaceAfter(Accessibility.ForSetter(navProperty))#>set { if ((value != null)) { ((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>", value); } } } <# } } region.End(); #> } <# } region.End(); //////// //////// Write ComplexType classes. //////// region.Begin(GetResourceString("Template_RegionComplexTypes")); foreach (ComplexType complex in GetSourceSchemaTypes().OrderBy(c => c.Name)) { #> /// /// <#=SummaryComment(complex)#> /// <#=LongDescriptionCommentElement(complex, region.CurrentIndentLevel)#> [EdmComplexTypeAttribute(NamespaceName="<#=complex.NamespaceName#>", Name="<#=complex.Name#>")] [DataContractAttribute(IsReference=true)] [Serializable()] [global::System.CodeDom.Compiler.GeneratedCode("EdmxTool", "1.0.0.0")] <#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#> : ComplexObject { <# WriteFactoryMethod(complex, code); region.Begin(GetResourceString("Template_RegionPrimitiveProperties")); foreach (EdmProperty property in complex.Properties.Where(p => p.DeclaringType == complex && p.TypeUsage.EdmType is PrimitiveType)) { VerifyGetterAndSetterAccessibilityCompatability(property); WritePrimitiveTypeProperty(property, code); } region.End(); region.Begin(GetResourceString("Template_RegionComplexProperties")); foreach (EdmProperty property in complex.Properties.Where(p => p.DeclaringType == complex && p.TypeUsage.EdmType is ComplexType)) { VerifyGetterAndSetterAccessibilityCompatability(property); WriteComplexTypeProperty(property, code); } region.End(); #> } <# } region.End(); #> <# if (!String.IsNullOrEmpty(namespaceName)) { PopIndent(); #> } <# } VerifyTypeUniqueness(); #> <#+ //////// //////// Reusable Template Sections //////// //////// //////// Write Factory Method. //////// private void WriteFactoryMethod(StructuralType structuralType, CodeGenerationTools code) { CodeRegion region = new CodeRegion(this, 1); string methodName = "Create" + structuralType.Name; UniqueIdentifierService uniqueIdentifier = new UniqueIdentifierService(); string instanceName = code.Escape(uniqueIdentifier.AdjustIdentifier((code.CamelCase(structuralType.Name)))); IEnumerable parameters = FactoryMethodParameter.CreateParameters(structuralType.Members.OfType().Where(p => IncludePropertyInFactoryMethod(structuralType, p)), uniqueIdentifier, MultiSchemaEscape, code); if (parameters.Count() == 0) return; if (structuralType.Members.Any(m => m.Name == methodName)) { // 6029 is the same error number that EntityClassGenerator uses for this conflict. Errors.Add(new System.CodeDom.Compiler.CompilerError(SourceCsdlPath, -1, -1, "6029", String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_FactoryMethodNameConflict"), methodName, structuralType.FullName))); } region.Begin(GetResourceString("Template_RegionFactoryMethod")); #> /// /// <#=String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_FactoryMethodComment"), structuralType.Name)#> /// <#=ParameterComments(parameters.Select(p => new Tuple(p.RawParameterName, p.ParameterComment)), region.CurrentIndentLevel)#> public static <#=code.Escape(structuralType)#> <#=methodName#>(<#=string.Join(", ", parameters.Select(p => p.ParameterType + " " + p.ParameterName).ToArray())#>) { <#=code.Escape(structuralType)#> <#=instanceName#> = new <#=code.Escape(structuralType)#>(); <#+ foreach (FactoryMethodParameter parameter in parameters) { if (parameter.IsComplexType) { // ComplexType initialization. #> <#=instanceName#>.<#=code.Escape(parameter.Source)#> = StructuralObject.VerifyComplexObjectIsNotNull(<#=parameter.ParameterName#>, "<#=parameter.Source.Name#>"); <#+ } else { // PrimitiveType initialization. #> <#=instanceName#>.<#=code.Escape(parameter.Source)#> = <#=parameter.ParameterName#>; <#+ } } #> return <#=instanceName#>; } <#+ region.End(); } //////// //////// Write PrimitiveType Properties. //////// private void WritePrimitiveTypeProperty(EdmProperty primitiveProperty, CodeGenerationTools code) { MetadataTools ef = new MetadataTools(this); #> /// /// <#=SummaryComment(primitiveProperty)#> /// <#=LongDescriptionCommentElement(primitiveProperty, 1)#> [EdmScalarPropertyAttribute(EntityKeyProperty=<#=CreateLiteral(ef.IsKey(primitiveProperty))#>, IsNullable=<#=CreateLiteral(ef.IsNullable(primitiveProperty))#>)] [DataMemberAttribute()] <#=code.SpaceAfter(NewModifier(primitiveProperty))#><#=Accessibility.ForProperty(primitiveProperty)#> <#=code.Escape(primitiveProperty.TypeUsage)#> <#=code.Escape(primitiveProperty)#> { <#=code.SpaceAfter(Accessibility.ForGetter(primitiveProperty))#>get { <#+ if (ef.ClrType(primitiveProperty.TypeUsage) == typeof(byte[])) { #> return StructuralObject.GetValidValue(<#=code.FieldName(primitiveProperty)#>); <#+ } else { #> return <#=code.FieldName(primitiveProperty)#>; <#+ } #> } <#=code.SpaceAfter(Accessibility.ForSetter((primitiveProperty)))#>set { <#+ if (ef.IsKey(primitiveProperty)) { if (ef.ClrType(primitiveProperty.TypeUsage) == typeof(byte[])) { #> if (!StructuralObject.BinaryEquals(<#=code.FieldName(primitiveProperty)#>, value)) <#+ } else { #> if (<#=code.FieldName(primitiveProperty)#> != value) <#+ } #> { <#+ PushIndent(CodeRegion.GetIndent(1)); } #> <#=ChangingMethodName(primitiveProperty)#>(value); ReportPropertyChanging("<#=primitiveProperty.Name#>"); <#=code.FieldName(primitiveProperty)#> = StructuralObject.SetValidValue(value<#=OptionalNullableParameterForSetValidValue(primitiveProperty)#>); ReportPropertyChanged("<#=primitiveProperty.Name#>"); <#=ChangedMethodName(primitiveProperty)#>(); <#+ if (ef.IsKey(primitiveProperty)) { PopIndent(); #> } <#+ } #> } } private <#=code.Escape(primitiveProperty.TypeUsage)#> <#=code.FieldName(primitiveProperty)#><#=code.StringBefore(" = ", CreateLiteral(primitiveProperty.DefaultValue))#>; partial void <#=ChangingMethodName(primitiveProperty)#>(<#=code.Escape(primitiveProperty.TypeUsage)#> value); partial void <#=ChangedMethodName(primitiveProperty)#>(); <#+ } //////// //////// Write ComplexType Properties. //////// private void WriteComplexTypeProperty(EdmProperty complexProperty, CodeGenerationTools code) { #> /// /// <#=SummaryComment(complexProperty)#> /// <#=LongDescriptionCommentElement(complexProperty, 1)#> [EdmComplexPropertyAttribute()] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [XmlElement(IsNullable=true)] [SoapElement(IsNullable=true)] [DataMemberAttribute()] <#=code.SpaceAfter(NewModifier(complexProperty))#><#=Accessibility.ForProperty(complexProperty)#> <#=MultiSchemaEscape(complexProperty.TypeUsage, code)#> <#=code.Escape(complexProperty)#> { <#=code.SpaceAfter(Accessibility.ForGetter(complexProperty))#>get { <#=code.FieldName(complexProperty)#> = GetValidValue(<#=code.FieldName(complexProperty)#>, "<#=complexProperty.Name#>", false, <#=InitializedTrackingField(complexProperty, code)#>); <#=InitializedTrackingField(complexProperty, code)#> = true; return <#=code.FieldName(complexProperty)#>; } <#=code.SpaceAfter(Accessibility.ForSetter(complexProperty))#>set { <#=ChangingMethodName(complexProperty)#>(value); ReportPropertyChanging("<#=complexProperty.Name#>"); <#=code.FieldName(complexProperty)#> = SetValidValue(<#=code.FieldName(complexProperty)#>, value, "<#=complexProperty.Name#>"); <#=InitializedTrackingField(complexProperty, code)#> = true; ReportPropertyChanged("<#=complexProperty.Name#>"); <#=ChangedMethodName(complexProperty)#>(); } } private <#=MultiSchemaEscape(complexProperty.TypeUsage, code)#> <#=code.FieldName(complexProperty)#>; private bool <#=InitializedTrackingField(complexProperty, code)#>; partial void <#=ChangingMethodName(complexProperty)#>(<#=MultiSchemaEscape(complexProperty.TypeUsage, code)#> value); partial void <#=ChangedMethodName(complexProperty)#>(); <#+ } private void WriteLazyLoadingEnabled(EntityContainer container) { string lazyLoadingAttributeValue = null; string lazyLoadingAttributeName = MetadataConstants.EDM_ANNOTATION_09_02 + ":LazyLoadingEnabled"; if(MetadataTools.TryGetStringMetadataPropertySetting(container, lazyLoadingAttributeName, out lazyLoadingAttributeValue)) { bool isLazyLoading = false; if(bool.TryParse(lazyLoadingAttributeValue, out isLazyLoading)) { #> this.ContextOptions.LazyLoadingEnabled = <#=isLazyLoading.ToString().ToLowerInvariant()#>; <#+ } } } //////// //////// Declare Template Public Properties. //////// public string SourceCsdlPath{ get; set; } public string ModelNamespace{ get; set; } public EdmItemCollection ItemCollection{ get; set; } public IEnumerable ReferenceCsdlPaths{ get; set; } public Nullable CreateContextAddToMethods{ get; set; } public Dictionary EdmToObjectNamespaceMap { get { return _edmToObjectNamespaceMap; } set { _edmToObjectNamespaceMap = value; } } public Dictionary _edmToObjectNamespaceMap = new Dictionary(); public Double SourceEdmVersion { get { if (ItemCollection != null) { return ItemCollection.EdmVersion; } return 0.0; } } //////// //////// Declare Template Private Properties. //////// static System.Resources.ResourceManager ResourceManager { get { if (_resourceManager == null) { System.Resources.ResourceManager resourceManager = new System.Resources.ResourceManager("System.Data.Entity.Design", typeof(System.Data.Entity.Design.MetadataItemCollectionFactory).Assembly); System.Threading.Interlocked.CompareExchange(ref _resourceManager, resourceManager, null); } return _resourceManager; } } static System.Resources.ResourceManager _resourceManager; #> <#+ private static string GetResourceString(string resourceName) { return ResourceManager.GetString(resourceName, null); // Take default culture. } private void VerifyTypeUniqueness() { HashSet hash = new HashSet(); IEnumerable allTypes = GetSourceSchemaTypes().Where(i => i is StructuralType || i is EntityContainer); foreach (GlobalItem type in allTypes) { if (!hash.Add(GetGlobalItemName(type))) { // 6034 is the error number used by System.Data.Entity.Design EntityClassGenerator. Errors.Add(new System.CodeDom.Compiler.CompilerError(SourceCsdlPath, -1, -1, "6034", String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_DuplicateTopLevelType"), GetGlobalItemName(type)))); } } } protected string GetGlobalItemName(GlobalItem item) { if (item is EdmType) { // EntityType or ComplexType. return ((EdmType)item).Name; } else { // Must be an EntityContainer. return ((EntityContainer)item).Name; } } void ApplyUserSettings(UserSettings userSettings) { // Setup template UserSettings. if (SourceCsdlPath == null) { #if !PREPROCESSED_TEMPLATE if(userSettings.SourceCsdlPath == "$" + "edmxInputFile" + "$") { Errors.Add(new System.CodeDom.Compiler.CompilerError(Host.TemplateFile, 0, 0, "", GetResourceString("Template_ReplaceVsItemTemplateToken"))); return; } SourceCsdlPath = Host.ResolvePath(userSettings.SourceCsdlPath); #else SourceCsdlPath = userSettings.SourceCsdlPath; #endif } // normalize the path, remove ..\ from it SourceCsdlPath = Path.GetFullPath(SourceCsdlPath); if (ReferenceCsdlPaths == null) { ReferenceCsdlPaths = userSettings.ReferenceCsdlPaths; } if (!CreateContextAddToMethods.HasValue) { CreateContextAddToMethods = userSettings.CreateContextAddToMethods; } DefaultSummaryComment = GetResourceString("Template_CommentNoDocumentation"); } class UserSettings { public string SourceCsdlPath{ get; set; } public string[] ReferenceCsdlPaths{ get; set; } public bool FullyQualifySystemTypes{ get; set; } public bool CreateContextAddToMethods{ get; set; } public bool CamelCaseFields{ get; set; } } string MultiSchemaEscape(TypeUsage usage, CodeGenerationTools code) { StructuralType structural = usage.EdmType as StructuralType; if (structural != null) { return MultiSchemaEscape(structural, code); } return code.Escape(usage); } string MultiSchemaEscape(StructuralType type, CodeGenerationTools code) { if (type.NamespaceName != ModelNamespace) { return code.CreateFullName(code.EscapeNamespace(GetObjectNamespace(type.NamespaceName)), code.Escape(type)); } return code.Escape(type); } string NewModifier(NavigationProperty navigationProperty) { Type baseType = typeof(EntityObject); return NewModifier(baseType, navigationProperty.Name); } string NewModifier(EdmFunction edmFunction) { Type baseType = typeof(ObjectContext); return NewModifier(baseType, edmFunction.Name); } string NewModifier(EntitySet set) { Type baseType = typeof(ObjectContext); return NewModifier(baseType, set.Name); } string NewModifier(EdmProperty property) { Type baseType; if (property.DeclaringType.BuiltInTypeKind == BuiltInTypeKind.EntityType) { baseType = typeof(EntityObject); } else { baseType = typeof(ComplexObject); } return NewModifier(baseType, property.Name); } string NewModifier(Type type, string memberName) { if (HasBaseMemberWithMatchingName(type, memberName)) { return "new"; } return string.Empty; } static bool HasBaseMemberWithMatchingName(Type type, string memberName) { BindingFlags bindingFlags = BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; return type.GetMembers(bindingFlags).Where(m => IsVisibleMember(m)).Any(m => m.Name == memberName); } string ChangingMethodName(EdmMember member) { return string.Format(CultureInfo.InvariantCulture, "On{0}Changing", member.Name); } string ChangedMethodName(EdmMember member) { return string.Format(CultureInfo.InvariantCulture, "On{0}Changed", member.Name); } string InitializedTrackingField(EdmProperty property, CodeGenerationTools code) { string namePart = property.Name + "Initialized"; if (code.CamelCaseFields) { namePart = code.CamelCase(namePart); } return "_" + namePart; } string OptionalNullableParameterForSetValidValue(EdmMember member) { MetadataTools ef = new MetadataTools(this); string list = string.Empty; if (((PrimitiveType)member.TypeUsage.EdmType).ClrEquivalentType.IsClass) { list += ", " + CreateLiteral(ef.IsNullable(member.TypeUsage)); } return list; } static bool IsVisibleMember(MemberInfo memberInfo) { if (memberInfo is EventInfo) { EventInfo ei = (EventInfo)memberInfo; MethodInfo add = ei.GetAddMethod(); MethodInfo remove = ei.GetRemoveMethod(); return IsVisibleMethod(add) || IsVisibleMethod(remove); } else if (memberInfo is FieldInfo) { FieldInfo fi = (FieldInfo)memberInfo; return !fi.IsPrivate && !fi.IsAssembly; } else if (memberInfo is MethodBase) { MethodBase mb = (MethodBase)memberInfo; if (mb.IsSpecialName) return false; return IsVisibleMethod(mb); } else if (memberInfo is PropertyInfo) { PropertyInfo pi = (PropertyInfo)memberInfo; MethodInfo get = pi.GetGetMethod(); MethodInfo set = pi.GetSetMethod(); return IsVisibleMethod(get) || IsVisibleMethod(set); } return false; } static bool IsVisibleMethod(MethodBase methodBase) { if (methodBase == null) return false; return !methodBase.IsPrivate && !methodBase.IsAssembly; } IEnumerable GetSourceSchemaTypes() where T : GlobalItem { if (Path.GetExtension(SourceCsdlPath) != ".edmx") { return ItemCollection.GetItems().Where(e => e.MetadataProperties.Any(mp => mp.Name == "SchemaSource" && (string)mp.Value == SourceCsdlPath)); } else { return ItemCollection.GetItems(); } } string EndName(AssociationType association, int index) { return association.AssociationEndMembers[index].Name; } string EndMultiplicity(AssociationType association, int index) { return CreateLiteral(association.AssociationEndMembers[index].RelationshipMultiplicity); } string EscapeEndTypeName(AssociationType association, int index, CodeGenerationTools code) { EntityType entity = association.AssociationEndMembers[index].GetEntityType(); return code.CreateFullName(code.EscapeNamespace(GetObjectNamespace(entity.NamespaceName)), code.Escape(entity)); } string GetObjectNamespace(string csdlNamespaceName) { string objectNamespace; if (EdmToObjectNamespaceMap.TryGetValue(csdlNamespaceName, out objectNamespace)) { return objectNamespace; } return csdlNamespaceName; } void UpdateObjectNamespaceMap(string objectNamespace) { if(objectNamespace != ModelNamespace && !EdmToObjectNamespaceMap.ContainsKey(ModelNamespace)) { EdmToObjectNamespaceMap.Add(ModelNamespace, objectNamespace); } } static string FixParameterName(string name, CodeGenerationTools code) { // Change any property that is 'id' (case insensitive) to 'ID' // since 'iD' is a violation of FxCop rules. if (StringComparer.OrdinalIgnoreCase.Equals(name, "id")) { // Return all lower case since it is an abbreviation, not an acronym. return "id"; } return code.CamelCase(name); } string BaseTypeName(EntityType entity, CodeGenerationTools code) { return entity.BaseType == null ? "EntityObject" : MultiSchemaEscape((StructuralType)entity.BaseType, code); } bool IncludePropertyInFactoryMethod(StructuralType factoryType, EdmProperty edmProperty) { if (edmProperty.Nullable) { return false; } if (edmProperty.DefaultValue != null) { return false; } if ((Accessibility.ForReadOnlyProperty(edmProperty) != "public" && Accessibility.ForWriteOnlyProperty(edmProperty) != "public") || (factoryType != edmProperty.DeclaringType && Accessibility.ForWriteOnlyProperty(edmProperty) == "private") ) { // There is no public part to the property. return false; } return true; } class FactoryMethodParameter { public EdmProperty Source; public string RawParameterName; public string ParameterName; public string ParameterType; public string ParameterComment; public bool IsComplexType; public static IEnumerable CreateParameters(IEnumerable properties, UniqueIdentifierService unique, Func multiSchemaEscape, CodeGenerationTools code) { List parameters = new List(); foreach (EdmProperty property in properties) { FactoryMethodParameter parameter = new FactoryMethodParameter(); parameter.Source = property; parameter.IsComplexType = property.TypeUsage.EdmType is ComplexType; parameter.RawParameterName = unique.AdjustIdentifier(FixParameterName(property.Name, code)); parameter.ParameterName = code.Escape(parameter.RawParameterName); parameter.ParameterType = multiSchemaEscape(property.TypeUsage, code); parameter.ParameterComment = String.Format(CultureInfo.CurrentCulture, GetResourceString("Template_CommentFactoryMethodParam"), property.Name); parameters.Add(parameter); } return parameters; } } string DefaultSummaryComment{ get; set; } string SummaryComment(MetadataItem item) { if (item.Documentation != null && item.Documentation.Summary != null) { return PrefixLinesOfMultilineComment(XMLCOMMENT_START + " ", XmlEntityize(item.Documentation.Summary)); } if (DefaultSummaryComment != null) { return DefaultSummaryComment; } return string.Empty; } string LongDescriptionCommentElement(MetadataItem item, int indentLevel) { if (item.Documentation != null && !String.IsNullOrEmpty(item.Documentation.LongDescription)) { string comment = Environment.NewLine; string lineStart = CodeRegion.GetIndent(indentLevel) + XMLCOMMENT_START + " "; comment += lineStart + "" + Environment.NewLine; comment += lineStart + PrefixLinesOfMultilineComment(lineStart, XmlEntityize(item.Documentation.LongDescription)) + Environment.NewLine; comment += lineStart + ""; return comment; } return string.Empty; } string PrefixLinesOfMultilineComment(string prefix, string comment) { return comment.Replace(Environment.NewLine, Environment.NewLine + prefix); } string ParameterComments(IEnumerable> parameters, int indentLevel) { System.Text.StringBuilder builder = new System.Text.StringBuilder(); foreach (Tuple parameter in parameters) { builder.AppendLine(); builder.Append(CodeRegion.GetIndent(indentLevel)); builder.Append(XMLCOMMENT_START); builder.Append(String.Format(CultureInfo.InvariantCulture, " {1}", parameter.Item1, parameter.Item2)); } return builder.ToString(); } string XmlEntityize(string text) { if (string.IsNullOrEmpty(text)) { return string.Empty; } text = text.Replace("&","&"); text = text.Replace("<","<").Replace(">",">"); string id = Guid.NewGuid().ToString(); text = text.Replace(Environment.NewLine, id); text = text.Replace("\r", " ").Replace("\n"," "); text = text.Replace(id, Environment.NewLine); return text.Replace("\'","'").Replace("\"","""); } const string XMLCOMMENT_START = "///"; IEnumerable GetProperties(StructuralType type) { if (type.BuiltInTypeKind == BuiltInTypeKind.EntityType) { return ((EntityType)type).Properties; } else { return ((ComplexType)type).Properties; } } string CreateLiteral(object value) { if (value == null) { return string.Empty; } Type type = value.GetType(); if (type.IsEnum) { return type.FullName + "." + value.ToString(); } if (type == typeof(Guid)) { return string.Format(CultureInfo.InvariantCulture, "new Guid(\"{0}\")", ((Guid)value).ToString("D", CultureInfo.InvariantCulture)); } else if (type == typeof(DateTime)) { return string.Format(CultureInfo.InvariantCulture, "new DateTime({0}, DateTimeKind.Unspecified)", ((DateTime)value).Ticks); } else if (type == typeof(byte[])) { var arrayInit = string.Join(", ", ((byte[])value).Select(b => b.ToString(CultureInfo.InvariantCulture)).ToArray()); return string.Format(CultureInfo.InvariantCulture, "new byte[] {{{0}}}", arrayInit); } else if (type == typeof(DateTimeOffset)) { var dto = (DateTimeOffset)value; return string.Format(CultureInfo.InvariantCulture, "new DateTimeOffset({0}, new TimeSpan({1}))", dto.Ticks, dto.Offset.Ticks); } var expression = new CodePrimitiveExpression(value); var writer = new StringWriter(); CSharpCodeProvider code = new CSharpCodeProvider(); code.GenerateCodeFromExpression(expression, writer, new CodeGeneratorOptions()); return writer.ToString(); } protected void VerifyGetterAndSetterAccessibilityCompatability(EdmMember member) { string rawGetterAccessibility = Accessibility.ForReadOnlyProperty(member); string rawSetterAccessibility = Accessibility.ForWriteOnlyProperty(member); if ((rawGetterAccessibility == "internal" && rawSetterAccessibility == "protected") || (rawGetterAccessibility == "protected" && rawSetterAccessibility == "internal")) { Errors.Add(new System.CodeDom.Compiler.CompilerError(SourceCsdlPath, -1, -1, "6033", String.Format(CultureInfo.CurrentCulture, GetResourceString("GeneratedPropertyAccessibilityConflict"), member.Name, rawGetterAccessibility, rawSetterAccessibility))); } } private void VerifyEntityTypeAndSetAccessibilityCompatability(EntitySet set) { string typeAccess = Accessibility.ForType(set.ElementType); string setAccess = Accessibility.ForReadOnlyProperty(set); if(typeAccess == "internal" && (setAccess == "public" || setAccess == "protected")) { Errors.Add(new System.CodeDom.Compiler.CompilerError(SourceCsdlPath, -1, -1, "6036", String.Format(CultureInfo.CurrentCulture, GetResourceString("EntityTypeAndSetAccessibilityConflict"), set.ElementType.Name, typeAccess, set.Name, setAccess))); } } //////// //////// UniqueIdentifierService //////// sealed class UniqueIdentifierService { private readonly HashSet _knownIdentifiers; public UniqueIdentifierService() { _knownIdentifiers = new HashSet(StringComparer.Ordinal); } /// /// Makes the supplied identifier unique within the scope by adding /// a suffix (1, 2, 3, ...), and returns the unique identifier. /// public string AdjustIdentifier(string identifier) { // find a unique name by adding suffix as necessary var numberOfConflicts = 0; var adjustedIdentifier = identifier; while (!_knownIdentifiers.Add(adjustedIdentifier)) { ++numberOfConflicts; adjustedIdentifier = identifier + numberOfConflicts.ToString(CultureInfo.InvariantCulture); } return adjustedIdentifier; } } #>