EntityContainerEmitter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntityDesign / Design / System / Data / EntityModel / Emitters / EntityContainerEmitter.cs / 1305376 / EntityContainerEmitter.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.CodeDom;
using System.Diagnostics;
using SOM = System.Data.EntityModel.SchemaObjectModel;
using System.Collections.Generic; 
using System.Data.Entity.Design;
using System.Data.Objects; 
using System.Data.Entity.Design.Common; 
using System.Data.Metadata.Edm;
using System.Data.Entity.Design.SsdlGenerator; 
using System.Linq;
using System.Data.Common.Utils;

 
namespace System.Data.EntityModel.Emitters
{ 
    ///  
    /// This class is responsible for emiting the code for the EntityContainer schema element
    ///  
    internal sealed class EntityContainerEmitter : SchemaTypeEmitter
    {
        #region Fields
        string _onContextCreatedString = "OnContextCreated"; 
        #endregion
 
 
        #region Constructors
 
        /// 
        ///
        /// 
        ///  
        /// 
        public EntityContainerEmitter(ClientApiGenerator generator, EntityContainer entityContainer) 
            : base(generator, entityContainer) 
        {
        } 

        #endregion

        #region Properties, Methods, Events & Delegates 
        /// 
        /// Creates the CodeTypeDeclarations necessary to generate the code for the EntityContainer schema element 
        ///  
        /// 
        public override CodeTypeDeclarationCollection EmitApiClass() 
        {
            Validate(); // emitter-specific validation

            // declare the new class 
            // public partial class LOBScenario : ObjectContext
            CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(Item.Name); 
            typeDecl.IsPartial = true; 

            // raise the TypeGenerated event 
            CodeTypeReference objectContextTypeRef = TypeReference.ObjectContext;
            TypeGeneratedEventArgs eventArgs = new TypeGeneratedEventArgs(Item, objectContextTypeRef);
            Generator.RaiseTypeGeneratedEvent(eventArgs);
 
            if (eventArgs.BaseType != null && !eventArgs.BaseType.Equals(objectContextTypeRef))
            { 
                typeDecl.BaseTypes.Add(eventArgs.BaseType); 
            }
            else 
            {
                typeDecl.BaseTypes.Add(TypeReference.ObjectContext);
            }
            AddInterfaces(Item.Name, typeDecl, eventArgs.AdditionalInterfaces); 

            CommentEmitter.EmitSummaryComments(Item, typeDecl.Comments); 
            EmitTypeAttributes(Item.Name, typeDecl, eventArgs.AdditionalAttributes); 

            CreateConstructors(typeDecl); 
            // adding partial OnContextCreated method
            CreateContextPartialMethods(typeDecl);

            foreach (EntitySetBase entitySetBase in Item.BaseEntitySets) 
            {
                if (MetadataUtil.IsEntitySet(entitySetBase)) 
                { 
                    EntitySet set = (EntitySet)entitySetBase;
                    CodeMemberProperty codeProperty = CreateEntitySetProperty(set); 
                    typeDecl.Members.Add(codeProperty);

                    CodeMemberField codeField = CreateEntitySetField(set);
                    typeDecl.Members.Add(codeField); 
                }
            } 
 
            foreach (EntitySetBase entitySetBase in Item.BaseEntitySets)
            { 
                if (MetadataUtil.IsEntitySet(entitySetBase))
                {
                    EntitySet set = (EntitySet)entitySetBase;
                    CodeMemberMethod codeProperty = CreateEntitySetAddObjectProperty(set); 
                    typeDecl.Members.Add(codeProperty);
                } 
            } 

            foreach (EdmFunction functionImport in Item.FunctionImports) 
            {
                if (ShouldEmitFunctionImport(functionImport))
                {
                    CodeMemberMethod functionMethod = CreateFunctionImportStructuralTypeReaderMethod(functionImport); 
                    typeDecl.Members.Add(functionMethod);
                } 
            } 

            // additional members, if provided by the event subscriber 
            AddMembers(Item.Name, typeDecl, eventArgs.AdditionalMembers);

            CodeTypeDeclarationCollection typeDecls = new CodeTypeDeclarationCollection();
            typeDecls.Add(typeDecl); 
            return typeDecls;
        } 
 
        private bool ShouldEmitFunctionImport(EdmFunction functionImport)
        { 
            EdmType returnType = GetReturnTypeFromFunctionImport(functionImport);

            StructuralType structuralReturnType = returnType as StructuralType;
 
            // we only code gen the functionimport that has a collection of EntityType as return type and ignore the rest,
            // to be more specific, the rest include no return type and collection of scalar type. 
            if (null != functionImport.EntitySet) 
            {
                return true; 
            }

            return false;
        } 

        private EdmType GetReturnTypeFromFunctionImport(EdmFunction functionImport) 
        { 
            EdmType returnType = null;
 
            if (null != functionImport.ReturnParameter)
            {
                // determine element return type
                returnType = functionImport.ReturnParameter.TypeUsage.EdmType; 

                if (Helper.IsCollectionType(returnType)) 
                { 
                    // get the type in the collection
                    returnType = ((CollectionType)returnType).TypeUsage.EdmType; 
                }
            }
            return returnType;
        } 

        ///  
        /// Emitter-specific validation: check if there exist entity containers and 
        /// entity sets that have the same name but differ in case
        ///  
        protected override void Validate()
        {
            base.Validate();
            Generator.VerifyLanguageCaseSensitiveCompatibilityForEntitySet(Item); 
            VerifyEntityTypeAndSetAccessibilityCompatability();
        } 
 
        /// 
        /// Verify that Entity Set and Type have compatible accessibilty. 
        /// They are compatible if the generated code will compile.
        /// 
        private void VerifyEntityTypeAndSetAccessibilityCompatability()
        { 
            foreach (EntitySetBase entitySetBase in Item.BaseEntitySets)
            { 
                if (MetadataUtil.IsEntitySet(entitySetBase)) 
                {
                    EntitySet set = (EntitySet)entitySetBase; 
                    if(!AreTypeAndSetAccessCompatible(GetEntityTypeAccessibility(set.ElementType), GetEntitySetPropertyAccessibility(set)))
                    {
                        Generator.AddError(
                            System.Data.Entity.Design.Strings.EntityTypeAndSetAccessibilityConflict( 
                                set.ElementType.Name, GetAccessibilityCsdlStringFromMemberAttribute(GetEntityTypeAccessibility(set.ElementType)), set.Name, GetAccessibilityCsdlStringFromMemberAttribute(GetEntitySetPropertyAccessibility(set))),
                            ModelBuilderErrorCode.EntityTypeAndSetAccessibilityConflict, 
                            EdmSchemaErrorSeverity.Error); 
                    }
                } 
            }
        }

 
        /// 
        /// Tells whether Entity Type's specified accessibility and Entity Set Property's specified Accessibility will work together (compile) when codegen'd. 
        /// False if (Type is internal and Set's Property is Public OR, type is internal and Set's property is protected). 
        /// True otherwise
        ///  
        private bool AreTypeAndSetAccessCompatible(MemberAttributes typeAccess, MemberAttributes setAccess)
        {
            return !(typeAccess == MemberAttributes.Assembly && (setAccess == MemberAttributes.Public || setAccess == MemberAttributes.Family));
        } 

 
        ///  
        /// Creates the necessary constructors for the entity container.
        ///  
        private void CreateConstructors(CodeTypeDeclaration typeDecl)
        {
            // Empty constructor.
            // 
            // public ctor()
            //    : base("name=" + ContainerName, "ContainerName") 
            // { 
            //      this.OnContextCreated();
            // } 
            CodeConstructor emptyCtor = new CodeConstructor();
            emptyCtor.Attributes = MemberAttributes.Public;
            emptyCtor.BaseConstructorArgs.Add(new CodePrimitiveExpression("name=" + Item.Name));
            emptyCtor.BaseConstructorArgs.Add(new CodePrimitiveExpression(Item.Name)); 
            CommentEmitter.EmitSummaryComments(Strings.EmptyCtorSummaryComment(Item.Name, Item.Name), emptyCtor.Comments);
 
            emptyCtor.Statements.Add(OnContextCreatedCodeMethodInvokeExpression()); 

            typeDecl.Members.Add(emptyCtor); 

            // Constructor that takes a connection string.
            //
            // public ctor(string connectionString) 
            //    : base(connectionString, "ContainerName")
            // { 
            //      this.OnContextCreated(); 
            // }
            CodeConstructor connectionStringCtor = new CodeConstructor(); 
            connectionStringCtor.Attributes = MemberAttributes.Public;
            CodeParameterDeclarationExpression connectionStringParam = new CodeParameterDeclarationExpression(TypeReference.String, "connectionString");
            connectionStringCtor.Parameters.Add(connectionStringParam);
            connectionStringCtor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression(connectionStringParam.Name)); 
            connectionStringCtor.BaseConstructorArgs.Add(new CodePrimitiveExpression(Item.Name));
            CommentEmitter.EmitSummaryComments(Strings.CtorSummaryComment(Item.Name), connectionStringCtor.Comments); 
 
            connectionStringCtor.Statements.Add(OnContextCreatedCodeMethodInvokeExpression());
 
            typeDecl.Members.Add(connectionStringCtor);

            // Constructor that takes a connection
            // 
            // public ctor(System.Data.EntityClient.EntityConnection connection)
            //    : base(connection, "ContainerName") 
            // { 
            //      this.OnContextCreated();
            // } 
            CodeConstructor connectionWorkspaceCtor = new CodeConstructor();
            connectionWorkspaceCtor.Attributes = MemberAttributes.Public;
            CodeParameterDeclarationExpression connectionParam = new CodeParameterDeclarationExpression(TypeReference.AdoEntityClientType("EntityConnection"), "connection");
            connectionWorkspaceCtor.Parameters.Add(connectionParam); 
            connectionWorkspaceCtor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression(connectionParam.Name));
            connectionWorkspaceCtor.BaseConstructorArgs.Add(new CodePrimitiveExpression(Item.Name)); 
            CommentEmitter.EmitSummaryComments(Strings.CtorSummaryComment(Item.Name), connectionWorkspaceCtor.Comments); 

            connectionWorkspaceCtor.Statements.Add(OnContextCreatedCodeMethodInvokeExpression()); 
            typeDecl.Members.Add(connectionWorkspaceCtor);
        }

        ///  
        /// Adds the OnContextCreated partial method for the entity container.
        ///  
        private void CreateContextPartialMethods(CodeTypeDeclaration typeDecl) 
        {
            CodeMemberMethod onContextCreatedPartialMethod = new CodeMemberMethod(); 
            onContextCreatedPartialMethod.Name = _onContextCreatedString;
            onContextCreatedPartialMethod.ReturnType = new CodeTypeReference(typeof(void));
            onContextCreatedPartialMethod.Attributes = MemberAttributes.Abstract | MemberAttributes.Public;
            typeDecl.Members.Add(onContextCreatedPartialMethod); 

            Generator.FixUps.Add(new FixUp(Item.Name + "." + _onContextCreatedString, FixUpType.MarkAbstractMethodAsPartial)); 
        } 

        private CodeMemberField CreateEntitySetField(EntitySet set) 
        {
            Debug.Assert(set != null, "Field is Null");

            // trying to get 
            //
            // For Version < 2: 
            // 
            // private ObjectQuery _Customers = null;
            // 
            // For Version >= 2:
            //
            // private ObjectSet _Customers = null;
 
            CodeMemberField codeField = new CodeMemberField();
            Generator.AttributeEmitter.EmitGeneratedCodeAttribute(codeField); 
            codeField.Attributes = MemberAttributes.Final | MemberAttributes.Private; 
            codeField.Name = Utils.FieldNameFromPropName(set.Name);
 

            CodeTypeReference genericParameter = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType);
            codeField.Type = TypeReference.AdoFrameworkGenericClass("ObjectQuery", genericParameter);
 
            return codeField;
        } 
 
        private CodeMemberProperty CreateEntitySetProperty(EntitySet set)
        { 
            Debug.Assert(set != null, "Property is Null");

            // trying to get
            // 
            // [System.ComponentModel.Browsable(false)]
            // public ObjectQuery Customers 
            // { 
            //      get
            //      { 
            //          if ((this._Customers == null))
            //          {
            //              this._Customers = base.CreateQuery("[Customers]");
            //          } 
            //          return this._Customers;
            //      } 
            // } 
            //
            CodeMemberProperty codeProperty = new CodeMemberProperty(); 
            Generator.AttributeEmitter.EmitGeneratedCodeAttribute(codeProperty);
            codeProperty.Attributes = MemberAttributes.Final | GetEntitySetPropertyAccessibility(set);
            codeProperty.Name = set.Name;
            codeProperty.HasGet = true; 
            codeProperty.HasSet = false;
 
            // Determine type to use for field/property and name of factory method on ObjectContext 
            string typeName = "ObjectQuery";
            string createMethodName = "CreateQuery"; 
            // When the EntitySet name is used as CommandText, it should be quoted
            string createMethodArgument = "[" + set.Name + "]";

            CodeTypeReference genericParameter = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType); 
            codeProperty.Type = TypeReference.AdoFrameworkGenericClass(typeName, genericParameter);
            string fieldName = Utils.FieldNameFromPropName(set.Name); 
 
            // raise the PropertyGenerated event before proceeding further
            PropertyGeneratedEventArgs eventArgs = new PropertyGeneratedEventArgs(set, fieldName, codeProperty.Type); 
            Generator.RaisePropertyGeneratedEvent(eventArgs);

            if (eventArgs.ReturnType == null || !eventArgs.ReturnType.Equals(codeProperty.Type))
            { 
                throw EDesignUtil.InvalidOperation(Strings.CannotChangePropertyReturnType(set.Name, Item.Name));
            } 
 
            List additionalAttributes = eventArgs.AdditionalAttributes;
            if (additionalAttributes != null && additionalAttributes.Count > 0) 
            {
                try
                {
                    codeProperty.CustomAttributes.AddRange(additionalAttributes.ToArray()); 
                }
                catch (ArgumentNullException e) 
                { 
                    Generator.AddError(Strings.InvalidAttributeSuppliedForProperty(Item.Name),
                                               ModelBuilderErrorCode.InvalidAttributeSuppliedForProperty, 
                                               EdmSchemaErrorSeverity.Error,
                                               e);
                }
            } 

            // we need to insert user-specified code before other/existing code, including 
            // the return statement 
            List additionalGetStatements = eventArgs.AdditionalGetStatements;
 
            if (additionalGetStatements != null && additionalGetStatements.Count > 0)
            {
                try
                { 
                    codeProperty.GetStatements.AddRange(additionalGetStatements.ToArray());
                } 
                catch (ArgumentNullException e) 
                {
                    Generator.AddError(Strings.InvalidGetStatementSuppliedForProperty(Item.Name), 
                                       ModelBuilderErrorCode.InvalidGetStatementSuppliedForProperty,
                                       EdmSchemaErrorSeverity.Error,
                                       e);
                } 
            }
 
            codeProperty.GetStatements.Add( 
                new CodeConditionStatement(
                    EmitExpressionEqualsNull(new CodeFieldReferenceExpression(ThisRef, fieldName)), 
                    new CodeAssignStatement(
                        new CodeFieldReferenceExpression(ThisRef, fieldName),
                        new CodeMethodInvokeExpression(
                            new CodeMethodReferenceExpression( 
                                new CodeBaseReferenceExpression(),
                                createMethodName, 
                                new CodeTypeReference[] { genericParameter } 
                            ),
                            new CodePrimitiveExpression(createMethodArgument) 
                        )
                    )
                )
            ); 

            codeProperty.GetStatements.Add( 
                new CodeMethodReturnStatement( 
                    new CodeFieldReferenceExpression(
                        ThisRef, 
                        fieldName
                    )
                )
            ); 

            // property summary 
            CommentEmitter.EmitSummaryComments(set, codeProperty.Comments); 

            return codeProperty; 
        }
        /// 
        /// Create an AddTo-EntitysetName methiod for each entityset in the context.
        ///  
        /// EntityContainerEntitySet that we will go over to get the existing entitysets.
        ///  Method definition  
 
        private CodeMemberMethod CreateEntitySetAddObjectProperty(EntitySet set)
        { 
            Debug.Assert(set != null, "Property is Null");

            // trying to get
            // 
            // public void AddToCustomer(Customer customer)
            // { 
            //      base.AddObject("Customer", customer); 
            // }
            CodeMemberMethod codeMethod = new CodeMemberMethod(); 
            Generator.AttributeEmitter.EmitGeneratedCodeAttribute(codeMethod);
            codeMethod.Attributes = MemberAttributes.Final | GetEntityTypeAccessibility(set.ElementType);
            codeMethod.Name = ("AddTo" + set.Name);
 
            CodeParameterDeclarationExpression parameter = new CodeParameterDeclarationExpression();
 
            parameter.Type = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType); 
            parameter.Name = Utils.FixParameterName(set.ElementType.Name);
            codeMethod.Parameters.Add(parameter); 

            codeMethod.ReturnType = new CodeTypeReference(typeof(void));

            codeMethod.Statements.Add( 
                new CodeMethodInvokeExpression(
                    new CodeBaseReferenceExpression(), 
                    "AddObject", 
                    new CodePrimitiveExpression(set.Name),
                    new CodeFieldReferenceExpression(null, parameter.Name) 
                )
            );

            // method summary 
            CommentEmitter.EmitSummaryComments(set, codeMethod.Comments);
            return codeMethod; 
        } 

        ///  
        /// Create a method entry point for a function import yielding an entity reader.
        /// 
        /// SOM for function import; must not be null and must yield
        /// an entity reader. 
        /// Method definition.
        private CodeMemberMethod CreateFunctionImportStructuralTypeReaderMethod(EdmFunction functionImport) 
        { 
            // Trying to get:
            // 
            ///// 
            ///// Documentation
            ///// 
            //public ObjectQueryResult MyFunctionImport(Nullable id, string foo) 
            //{
            //    ObjectParameter idParameter; 
            //    if (id.HasValue) 
            //    {
            //        idParameter = new ObjectParameter("id", id); 
            //    }
            //    else
            //    {
            //        idParameter = new ObjectParameter("id", typeof(int)); 
            //    }
            //    ObjectParameter fooParameter; 
            //    if (null != foo) 
            //    {
            //        fooParameter = new ObjectParameter("foo", foo); 
            //    }
            //    else
            //    {
            //        fooParameter = new ObjectParameter("foo", typeof(string)); 
            //    }
            //    return base.ExecuteFunction("MyFunctionImport", idParameter, fooParameter); 
            //} 
            Debug.Assert(null != functionImport);
 
            CodeMemberMethod method = new CodeMemberMethod();
            Generator.AttributeEmitter.EmitGeneratedCodeAttribute(method);
            method.Name = functionImport.Name;
            method.Attributes = GetFunctionImportAccessibility(functionImport) | MemberAttributes.Final; 

            UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService( 
                this.Generator.IsLanguageCaseSensitive, 
                s => Utils.FixParameterName(s));
 
            // determine element return type
            EdmType returnType = GetReturnTypeFromFunctionImport(functionImport);
            if (Helper.IsCollectionType(returnType))
            { 
                // get the type in the collection
                returnType = ((CollectionType)returnType).TypeUsage.EdmType; 
            } 
            CodeTypeReference elementType = Generator.GetLeastPossibleQualifiedTypeReference(returnType);
            method.ReturnType = TypeReference.ObjectResult(elementType); 

            // generate  comments based on CSDL Documentation element
            CommentEmitter.EmitSummaryComments(functionImport, method.Comments);
 
            // build up list of arguments to ExecuteFunction
            List executeArguments = new List(); 
            executeArguments.Add(new CodePrimitiveExpression(functionImport.Name)); // first argument is the name of the function 
            foreach (FunctionParameter parameter in functionImport.Parameters)
            { 
                CreateFunctionArgument(method, uniqueIdentifierService, parameter);
            }

            // add fields representing object parameters 
            foreach (FunctionParameter parameter in functionImport.Parameters)
            { 
                if (parameter.Mode == ParameterMode.In) 
                {
                    CodeExpression variableReference = CreateFunctionParameter(method, uniqueIdentifierService, parameter); 
                    executeArguments.Add(variableReference);
                }
                else
                { 
                    // the parameter is already being passed in as an argument; just remember it and
                    // pass it in as an argument 
                    string adjustedParameterName; 
                    if (!uniqueIdentifierService.TryGetAdjustedName(parameter, out adjustedParameterName))
                    { 
                        Debug.Fail("parameter must be registered in identifier service");
                    }
                    executeArguments.Add(new CodeVariableReferenceExpression(adjustedParameterName));
                } 
            }
 
            // Add call to ExecuteFunction 
            //      return ExecuteFunction("FunctionImportName", { object parameters });
            CodeMethodReferenceExpression executeFunctionMethod = new CodeMethodReferenceExpression( 
                new CodeBaseReferenceExpression(),
                "ExecuteFunction",
                new CodeTypeReference[] { elementType });
            method.Statements.Add( 
                new CodeMethodReturnStatement(
                    new CodeMethodInvokeExpression(executeFunctionMethod, executeArguments.ToArray()) 
                ) 
            );
 
            // invoke the ExecuteFunction method passing in parameters
            return method;
        }
 
        private CodeExpression CreateFunctionParameter(CodeMemberMethod method, UniqueIdentifierService uniqueIdentifierService, FunctionParameter parameter)
        { 
            // get (adjusted) name of parameter 
            string adjustedParameterName;
            if (!uniqueIdentifierService.TryGetAdjustedName(parameter, out adjustedParameterName)) 
            {
                Debug.Fail("parameter must be registered in identifier service");
            }
            Type parameterType = DetermineParameterType(parameter); 

            // make sure the variable name does not collide with any parameters to the method, or any 
            // existing variables (all registered in the service) 
            string variableName = uniqueIdentifierService.AdjustIdentifier(parameter.Name + "Parameter");
 
            // ObjectParameter variableName;
            // if (null != parameterName)
            // {
            //     variableName = new ObjectParameter("parameterName", adjustedParameterName); 
            // }
            // else 
            // { 
            //     variableName = new ObjectParameter("parameterName", typeof(parameterType));
            // } 
            method.Statements.Add(
                new CodeVariableDeclarationStatement(TypeReference.ForType(typeof(ObjectParameter)), variableName));
            CodeExpression variableReference = new CodeVariableReferenceExpression(variableName);
            CodeExpression parameterReference = new CodeVariableReferenceExpression(adjustedParameterName); 
            CodeStatement nullConstructor = new CodeAssignStatement(variableReference,
                new CodeObjectCreateExpression(TypeReference.ForType(typeof(ObjectParameter)), 
                new CodePrimitiveExpression(parameter.Name), 
                new CodeTypeOfExpression(TypeReference.ForType(parameterType))));
            CodeStatement valueConstructor = new CodeAssignStatement(variableReference, 
                new CodeObjectCreateExpression(TypeReference.ForType(typeof(ObjectParameter)),
                new CodePrimitiveExpression(parameter.Name),
                parameterReference));
            CodeExpression notNullCondition; 
            if (parameterType.IsValueType)
            { 
                // Value type parameters generate Nullable arguments (see CreateFunctionArgument). 
                // We call Nullable.HasValue to determine whether the argument passed in is null
                // (since null != nullableTypeInstance does not work in VB) 
                //
                // parameterReference.HasValue
                notNullCondition = new CodePropertyReferenceExpression(
                    parameterReference, 
                    "HasValue");
            } 
            else 
            {
                // use parameterReference != null 
                notNullCondition = new CodeBinaryOperatorExpression(
                    parameterReference,
                    CodeBinaryOperatorType.IdentityInequality,
                    NullExpression); 
            }
            method.Statements.Add( 
                new CodeConditionStatement( 
                    notNullCondition,
                    new CodeStatement[] { valueConstructor, }, 
                    new CodeStatement[] { nullConstructor, }
                )
            );
            return variableReference; 
        }
 
        private void CreateFunctionArgument(CodeMemberMethod method, UniqueIdentifierService uniqueIdentifierService, FunctionParameter parameter) 
        {
            // get type of parameter 
            Type clrType = DetermineParameterType(parameter);

            // parameters to stored procedures must be nullable
            CodeTypeReference argumentType = clrType.IsValueType ? TypeReference.NullableForType(clrType) : TypeReference.ForType(clrType); 
            string parameterName = uniqueIdentifierService.AdjustIdentifier(parameter.Name, parameter);
            CodeParameterDeclarationExpression codeParameter = new CodeParameterDeclarationExpression(argumentType, parameterName); 
            method.Parameters.Add(codeParameter); 
        }
 
        // requires: parameter type is constrained to be a scalar type
        // Determines CLR type for function parameter
        private static Type DetermineParameterType(FunctionParameter parameter)
        { 
            Debug.Assert(null != parameter && MetadataUtil.IsPrimitiveType(parameter.TypeUsage.EdmType),
                "validation must ensure only scalar type parameter are given"); 
 
            if (parameter.Mode != ParameterMode.In)
            { 
                // non input parameter must be treated as ObjectParameter instances so that the
                // value can be set asynchronously (after the method has yielded and the reader
                // has been consumed)
                return typeof(ObjectParameter); 
            }
 
            PrimitiveType parameterType = (PrimitiveType)parameter.TypeUsage.EdmType; 
            Type clrType = parameterType.ClrType;
            return clrType; 
        }

        /// 
        /// return a code expression for invoking OnContextCreated partial method 
        /// 
        private CodeMethodInvokeExpression OnContextCreatedCodeMethodInvokeExpression() 
        { 
            return (new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), _onContextCreatedString, new CodeExpression[] { }));
        } 

        /// 
        /// Returns the type specific SchemaElement
        ///  
        private new EntityContainer Item
        { 
            get 
            {
                return base.Item as EntityContainer; 
            }
        }

        #endregion 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.CodeDom;
using System.Diagnostics;
using SOM = System.Data.EntityModel.SchemaObjectModel;
using System.Collections.Generic; 
using System.Data.Entity.Design;
using System.Data.Objects; 
using System.Data.Entity.Design.Common; 
using System.Data.Metadata.Edm;
using System.Data.Entity.Design.SsdlGenerator; 
using System.Linq;
using System.Data.Common.Utils;

 
namespace System.Data.EntityModel.Emitters
{ 
    ///  
    /// This class is responsible for emiting the code for the EntityContainer schema element
    ///  
    internal sealed class EntityContainerEmitter : SchemaTypeEmitter
    {
        #region Fields
        string _onContextCreatedString = "OnContextCreated"; 
        #endregion
 
 
        #region Constructors
 
        /// 
        ///
        /// 
        ///  
        /// 
        public EntityContainerEmitter(ClientApiGenerator generator, EntityContainer entityContainer) 
            : base(generator, entityContainer) 
        {
        } 

        #endregion

        #region Properties, Methods, Events & Delegates 
        /// 
        /// Creates the CodeTypeDeclarations necessary to generate the code for the EntityContainer schema element 
        ///  
        /// 
        public override CodeTypeDeclarationCollection EmitApiClass() 
        {
            Validate(); // emitter-specific validation

            // declare the new class 
            // public partial class LOBScenario : ObjectContext
            CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(Item.Name); 
            typeDecl.IsPartial = true; 

            // raise the TypeGenerated event 
            CodeTypeReference objectContextTypeRef = TypeReference.ObjectContext;
            TypeGeneratedEventArgs eventArgs = new TypeGeneratedEventArgs(Item, objectContextTypeRef);
            Generator.RaiseTypeGeneratedEvent(eventArgs);
 
            if (eventArgs.BaseType != null && !eventArgs.BaseType.Equals(objectContextTypeRef))
            { 
                typeDecl.BaseTypes.Add(eventArgs.BaseType); 
            }
            else 
            {
                typeDecl.BaseTypes.Add(TypeReference.ObjectContext);
            }
            AddInterfaces(Item.Name, typeDecl, eventArgs.AdditionalInterfaces); 

            CommentEmitter.EmitSummaryComments(Item, typeDecl.Comments); 
            EmitTypeAttributes(Item.Name, typeDecl, eventArgs.AdditionalAttributes); 

            CreateConstructors(typeDecl); 
            // adding partial OnContextCreated method
            CreateContextPartialMethods(typeDecl);

            foreach (EntitySetBase entitySetBase in Item.BaseEntitySets) 
            {
                if (MetadataUtil.IsEntitySet(entitySetBase)) 
                { 
                    EntitySet set = (EntitySet)entitySetBase;
                    CodeMemberProperty codeProperty = CreateEntitySetProperty(set); 
                    typeDecl.Members.Add(codeProperty);

                    CodeMemberField codeField = CreateEntitySetField(set);
                    typeDecl.Members.Add(codeField); 
                }
            } 
 
            foreach (EntitySetBase entitySetBase in Item.BaseEntitySets)
            { 
                if (MetadataUtil.IsEntitySet(entitySetBase))
                {
                    EntitySet set = (EntitySet)entitySetBase;
                    CodeMemberMethod codeProperty = CreateEntitySetAddObjectProperty(set); 
                    typeDecl.Members.Add(codeProperty);
                } 
            } 

            foreach (EdmFunction functionImport in Item.FunctionImports) 
            {
                if (ShouldEmitFunctionImport(functionImport))
                {
                    CodeMemberMethod functionMethod = CreateFunctionImportStructuralTypeReaderMethod(functionImport); 
                    typeDecl.Members.Add(functionMethod);
                } 
            } 

            // additional members, if provided by the event subscriber 
            AddMembers(Item.Name, typeDecl, eventArgs.AdditionalMembers);

            CodeTypeDeclarationCollection typeDecls = new CodeTypeDeclarationCollection();
            typeDecls.Add(typeDecl); 
            return typeDecls;
        } 
 
        private bool ShouldEmitFunctionImport(EdmFunction functionImport)
        { 
            EdmType returnType = GetReturnTypeFromFunctionImport(functionImport);

            StructuralType structuralReturnType = returnType as StructuralType;
 
            // we only code gen the functionimport that has a collection of EntityType as return type and ignore the rest,
            // to be more specific, the rest include no return type and collection of scalar type. 
            if (null != functionImport.EntitySet) 
            {
                return true; 
            }

            return false;
        } 

        private EdmType GetReturnTypeFromFunctionImport(EdmFunction functionImport) 
        { 
            EdmType returnType = null;
 
            if (null != functionImport.ReturnParameter)
            {
                // determine element return type
                returnType = functionImport.ReturnParameter.TypeUsage.EdmType; 

                if (Helper.IsCollectionType(returnType)) 
                { 
                    // get the type in the collection
                    returnType = ((CollectionType)returnType).TypeUsage.EdmType; 
                }
            }
            return returnType;
        } 

        ///  
        /// Emitter-specific validation: check if there exist entity containers and 
        /// entity sets that have the same name but differ in case
        ///  
        protected override void Validate()
        {
            base.Validate();
            Generator.VerifyLanguageCaseSensitiveCompatibilityForEntitySet(Item); 
            VerifyEntityTypeAndSetAccessibilityCompatability();
        } 
 
        /// 
        /// Verify that Entity Set and Type have compatible accessibilty. 
        /// They are compatible if the generated code will compile.
        /// 
        private void VerifyEntityTypeAndSetAccessibilityCompatability()
        { 
            foreach (EntitySetBase entitySetBase in Item.BaseEntitySets)
            { 
                if (MetadataUtil.IsEntitySet(entitySetBase)) 
                {
                    EntitySet set = (EntitySet)entitySetBase; 
                    if(!AreTypeAndSetAccessCompatible(GetEntityTypeAccessibility(set.ElementType), GetEntitySetPropertyAccessibility(set)))
                    {
                        Generator.AddError(
                            System.Data.Entity.Design.Strings.EntityTypeAndSetAccessibilityConflict( 
                                set.ElementType.Name, GetAccessibilityCsdlStringFromMemberAttribute(GetEntityTypeAccessibility(set.ElementType)), set.Name, GetAccessibilityCsdlStringFromMemberAttribute(GetEntitySetPropertyAccessibility(set))),
                            ModelBuilderErrorCode.EntityTypeAndSetAccessibilityConflict, 
                            EdmSchemaErrorSeverity.Error); 
                    }
                } 
            }
        }

 
        /// 
        /// Tells whether Entity Type's specified accessibility and Entity Set Property's specified Accessibility will work together (compile) when codegen'd. 
        /// False if (Type is internal and Set's Property is Public OR, type is internal and Set's property is protected). 
        /// True otherwise
        ///  
        private bool AreTypeAndSetAccessCompatible(MemberAttributes typeAccess, MemberAttributes setAccess)
        {
            return !(typeAccess == MemberAttributes.Assembly && (setAccess == MemberAttributes.Public || setAccess == MemberAttributes.Family));
        } 

 
        ///  
        /// Creates the necessary constructors for the entity container.
        ///  
        private void CreateConstructors(CodeTypeDeclaration typeDecl)
        {
            // Empty constructor.
            // 
            // public ctor()
            //    : base("name=" + ContainerName, "ContainerName") 
            // { 
            //      this.OnContextCreated();
            // } 
            CodeConstructor emptyCtor = new CodeConstructor();
            emptyCtor.Attributes = MemberAttributes.Public;
            emptyCtor.BaseConstructorArgs.Add(new CodePrimitiveExpression("name=" + Item.Name));
            emptyCtor.BaseConstructorArgs.Add(new CodePrimitiveExpression(Item.Name)); 
            CommentEmitter.EmitSummaryComments(Strings.EmptyCtorSummaryComment(Item.Name, Item.Name), emptyCtor.Comments);
 
            emptyCtor.Statements.Add(OnContextCreatedCodeMethodInvokeExpression()); 

            typeDecl.Members.Add(emptyCtor); 

            // Constructor that takes a connection string.
            //
            // public ctor(string connectionString) 
            //    : base(connectionString, "ContainerName")
            // { 
            //      this.OnContextCreated(); 
            // }
            CodeConstructor connectionStringCtor = new CodeConstructor(); 
            connectionStringCtor.Attributes = MemberAttributes.Public;
            CodeParameterDeclarationExpression connectionStringParam = new CodeParameterDeclarationExpression(TypeReference.String, "connectionString");
            connectionStringCtor.Parameters.Add(connectionStringParam);
            connectionStringCtor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression(connectionStringParam.Name)); 
            connectionStringCtor.BaseConstructorArgs.Add(new CodePrimitiveExpression(Item.Name));
            CommentEmitter.EmitSummaryComments(Strings.CtorSummaryComment(Item.Name), connectionStringCtor.Comments); 
 
            connectionStringCtor.Statements.Add(OnContextCreatedCodeMethodInvokeExpression());
 
            typeDecl.Members.Add(connectionStringCtor);

            // Constructor that takes a connection
            // 
            // public ctor(System.Data.EntityClient.EntityConnection connection)
            //    : base(connection, "ContainerName") 
            // { 
            //      this.OnContextCreated();
            // } 
            CodeConstructor connectionWorkspaceCtor = new CodeConstructor();
            connectionWorkspaceCtor.Attributes = MemberAttributes.Public;
            CodeParameterDeclarationExpression connectionParam = new CodeParameterDeclarationExpression(TypeReference.AdoEntityClientType("EntityConnection"), "connection");
            connectionWorkspaceCtor.Parameters.Add(connectionParam); 
            connectionWorkspaceCtor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression(connectionParam.Name));
            connectionWorkspaceCtor.BaseConstructorArgs.Add(new CodePrimitiveExpression(Item.Name)); 
            CommentEmitter.EmitSummaryComments(Strings.CtorSummaryComment(Item.Name), connectionWorkspaceCtor.Comments); 

            connectionWorkspaceCtor.Statements.Add(OnContextCreatedCodeMethodInvokeExpression()); 
            typeDecl.Members.Add(connectionWorkspaceCtor);
        }

        ///  
        /// Adds the OnContextCreated partial method for the entity container.
        ///  
        private void CreateContextPartialMethods(CodeTypeDeclaration typeDecl) 
        {
            CodeMemberMethod onContextCreatedPartialMethod = new CodeMemberMethod(); 
            onContextCreatedPartialMethod.Name = _onContextCreatedString;
            onContextCreatedPartialMethod.ReturnType = new CodeTypeReference(typeof(void));
            onContextCreatedPartialMethod.Attributes = MemberAttributes.Abstract | MemberAttributes.Public;
            typeDecl.Members.Add(onContextCreatedPartialMethod); 

            Generator.FixUps.Add(new FixUp(Item.Name + "." + _onContextCreatedString, FixUpType.MarkAbstractMethodAsPartial)); 
        } 

        private CodeMemberField CreateEntitySetField(EntitySet set) 
        {
            Debug.Assert(set != null, "Field is Null");

            // trying to get 
            //
            // For Version < 2: 
            // 
            // private ObjectQuery _Customers = null;
            // 
            // For Version >= 2:
            //
            // private ObjectSet _Customers = null;
 
            CodeMemberField codeField = new CodeMemberField();
            Generator.AttributeEmitter.EmitGeneratedCodeAttribute(codeField); 
            codeField.Attributes = MemberAttributes.Final | MemberAttributes.Private; 
            codeField.Name = Utils.FieldNameFromPropName(set.Name);
 

            CodeTypeReference genericParameter = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType);
            codeField.Type = TypeReference.AdoFrameworkGenericClass("ObjectQuery", genericParameter);
 
            return codeField;
        } 
 
        private CodeMemberProperty CreateEntitySetProperty(EntitySet set)
        { 
            Debug.Assert(set != null, "Property is Null");

            // trying to get
            // 
            // [System.ComponentModel.Browsable(false)]
            // public ObjectQuery Customers 
            // { 
            //      get
            //      { 
            //          if ((this._Customers == null))
            //          {
            //              this._Customers = base.CreateQuery("[Customers]");
            //          } 
            //          return this._Customers;
            //      } 
            // } 
            //
            CodeMemberProperty codeProperty = new CodeMemberProperty(); 
            Generator.AttributeEmitter.EmitGeneratedCodeAttribute(codeProperty);
            codeProperty.Attributes = MemberAttributes.Final | GetEntitySetPropertyAccessibility(set);
            codeProperty.Name = set.Name;
            codeProperty.HasGet = true; 
            codeProperty.HasSet = false;
 
            // Determine type to use for field/property and name of factory method on ObjectContext 
            string typeName = "ObjectQuery";
            string createMethodName = "CreateQuery"; 
            // When the EntitySet name is used as CommandText, it should be quoted
            string createMethodArgument = "[" + set.Name + "]";

            CodeTypeReference genericParameter = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType); 
            codeProperty.Type = TypeReference.AdoFrameworkGenericClass(typeName, genericParameter);
            string fieldName = Utils.FieldNameFromPropName(set.Name); 
 
            // raise the PropertyGenerated event before proceeding further
            PropertyGeneratedEventArgs eventArgs = new PropertyGeneratedEventArgs(set, fieldName, codeProperty.Type); 
            Generator.RaisePropertyGeneratedEvent(eventArgs);

            if (eventArgs.ReturnType == null || !eventArgs.ReturnType.Equals(codeProperty.Type))
            { 
                throw EDesignUtil.InvalidOperation(Strings.CannotChangePropertyReturnType(set.Name, Item.Name));
            } 
 
            List additionalAttributes = eventArgs.AdditionalAttributes;
            if (additionalAttributes != null && additionalAttributes.Count > 0) 
            {
                try
                {
                    codeProperty.CustomAttributes.AddRange(additionalAttributes.ToArray()); 
                }
                catch (ArgumentNullException e) 
                { 
                    Generator.AddError(Strings.InvalidAttributeSuppliedForProperty(Item.Name),
                                               ModelBuilderErrorCode.InvalidAttributeSuppliedForProperty, 
                                               EdmSchemaErrorSeverity.Error,
                                               e);
                }
            } 

            // we need to insert user-specified code before other/existing code, including 
            // the return statement 
            List additionalGetStatements = eventArgs.AdditionalGetStatements;
 
            if (additionalGetStatements != null && additionalGetStatements.Count > 0)
            {
                try
                { 
                    codeProperty.GetStatements.AddRange(additionalGetStatements.ToArray());
                } 
                catch (ArgumentNullException e) 
                {
                    Generator.AddError(Strings.InvalidGetStatementSuppliedForProperty(Item.Name), 
                                       ModelBuilderErrorCode.InvalidGetStatementSuppliedForProperty,
                                       EdmSchemaErrorSeverity.Error,
                                       e);
                } 
            }
 
            codeProperty.GetStatements.Add( 
                new CodeConditionStatement(
                    EmitExpressionEqualsNull(new CodeFieldReferenceExpression(ThisRef, fieldName)), 
                    new CodeAssignStatement(
                        new CodeFieldReferenceExpression(ThisRef, fieldName),
                        new CodeMethodInvokeExpression(
                            new CodeMethodReferenceExpression( 
                                new CodeBaseReferenceExpression(),
                                createMethodName, 
                                new CodeTypeReference[] { genericParameter } 
                            ),
                            new CodePrimitiveExpression(createMethodArgument) 
                        )
                    )
                )
            ); 

            codeProperty.GetStatements.Add( 
                new CodeMethodReturnStatement( 
                    new CodeFieldReferenceExpression(
                        ThisRef, 
                        fieldName
                    )
                )
            ); 

            // property summary 
            CommentEmitter.EmitSummaryComments(set, codeProperty.Comments); 

            return codeProperty; 
        }
        /// 
        /// Create an AddTo-EntitysetName methiod for each entityset in the context.
        ///  
        /// EntityContainerEntitySet that we will go over to get the existing entitysets.
        ///  Method definition  
 
        private CodeMemberMethod CreateEntitySetAddObjectProperty(EntitySet set)
        { 
            Debug.Assert(set != null, "Property is Null");

            // trying to get
            // 
            // public void AddToCustomer(Customer customer)
            // { 
            //      base.AddObject("Customer", customer); 
            // }
            CodeMemberMethod codeMethod = new CodeMemberMethod(); 
            Generator.AttributeEmitter.EmitGeneratedCodeAttribute(codeMethod);
            codeMethod.Attributes = MemberAttributes.Final | GetEntityTypeAccessibility(set.ElementType);
            codeMethod.Name = ("AddTo" + set.Name);
 
            CodeParameterDeclarationExpression parameter = new CodeParameterDeclarationExpression();
 
            parameter.Type = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType); 
            parameter.Name = Utils.FixParameterName(set.ElementType.Name);
            codeMethod.Parameters.Add(parameter); 

            codeMethod.ReturnType = new CodeTypeReference(typeof(void));

            codeMethod.Statements.Add( 
                new CodeMethodInvokeExpression(
                    new CodeBaseReferenceExpression(), 
                    "AddObject", 
                    new CodePrimitiveExpression(set.Name),
                    new CodeFieldReferenceExpression(null, parameter.Name) 
                )
            );

            // method summary 
            CommentEmitter.EmitSummaryComments(set, codeMethod.Comments);
            return codeMethod; 
        } 

        ///  
        /// Create a method entry point for a function import yielding an entity reader.
        /// 
        /// SOM for function import; must not be null and must yield
        /// an entity reader. 
        /// Method definition.
        private CodeMemberMethod CreateFunctionImportStructuralTypeReaderMethod(EdmFunction functionImport) 
        { 
            // Trying to get:
            // 
            ///// 
            ///// Documentation
            ///// 
            //public ObjectQueryResult MyFunctionImport(Nullable id, string foo) 
            //{
            //    ObjectParameter idParameter; 
            //    if (id.HasValue) 
            //    {
            //        idParameter = new ObjectParameter("id", id); 
            //    }
            //    else
            //    {
            //        idParameter = new ObjectParameter("id", typeof(int)); 
            //    }
            //    ObjectParameter fooParameter; 
            //    if (null != foo) 
            //    {
            //        fooParameter = new ObjectParameter("foo", foo); 
            //    }
            //    else
            //    {
            //        fooParameter = new ObjectParameter("foo", typeof(string)); 
            //    }
            //    return base.ExecuteFunction("MyFunctionImport", idParameter, fooParameter); 
            //} 
            Debug.Assert(null != functionImport);
 
            CodeMemberMethod method = new CodeMemberMethod();
            Generator.AttributeEmitter.EmitGeneratedCodeAttribute(method);
            method.Name = functionImport.Name;
            method.Attributes = GetFunctionImportAccessibility(functionImport) | MemberAttributes.Final; 

            UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService( 
                this.Generator.IsLanguageCaseSensitive, 
                s => Utils.FixParameterName(s));
 
            // determine element return type
            EdmType returnType = GetReturnTypeFromFunctionImport(functionImport);
            if (Helper.IsCollectionType(returnType))
            { 
                // get the type in the collection
                returnType = ((CollectionType)returnType).TypeUsage.EdmType; 
            } 
            CodeTypeReference elementType = Generator.GetLeastPossibleQualifiedTypeReference(returnType);
            method.ReturnType = TypeReference.ObjectResult(elementType); 

            // generate  comments based on CSDL Documentation element
            CommentEmitter.EmitSummaryComments(functionImport, method.Comments);
 
            // build up list of arguments to ExecuteFunction
            List executeArguments = new List(); 
            executeArguments.Add(new CodePrimitiveExpression(functionImport.Name)); // first argument is the name of the function 
            foreach (FunctionParameter parameter in functionImport.Parameters)
            { 
                CreateFunctionArgument(method, uniqueIdentifierService, parameter);
            }

            // add fields representing object parameters 
            foreach (FunctionParameter parameter in functionImport.Parameters)
            { 
                if (parameter.Mode == ParameterMode.In) 
                {
                    CodeExpression variableReference = CreateFunctionParameter(method, uniqueIdentifierService, parameter); 
                    executeArguments.Add(variableReference);
                }
                else
                { 
                    // the parameter is already being passed in as an argument; just remember it and
                    // pass it in as an argument 
                    string adjustedParameterName; 
                    if (!uniqueIdentifierService.TryGetAdjustedName(parameter, out adjustedParameterName))
                    { 
                        Debug.Fail("parameter must be registered in identifier service");
                    }
                    executeArguments.Add(new CodeVariableReferenceExpression(adjustedParameterName));
                } 
            }
 
            // Add call to ExecuteFunction 
            //      return ExecuteFunction("FunctionImportName", { object parameters });
            CodeMethodReferenceExpression executeFunctionMethod = new CodeMethodReferenceExpression( 
                new CodeBaseReferenceExpression(),
                "ExecuteFunction",
                new CodeTypeReference[] { elementType });
            method.Statements.Add( 
                new CodeMethodReturnStatement(
                    new CodeMethodInvokeExpression(executeFunctionMethod, executeArguments.ToArray()) 
                ) 
            );
 
            // invoke the ExecuteFunction method passing in parameters
            return method;
        }
 
        private CodeExpression CreateFunctionParameter(CodeMemberMethod method, UniqueIdentifierService uniqueIdentifierService, FunctionParameter parameter)
        { 
            // get (adjusted) name of parameter 
            string adjustedParameterName;
            if (!uniqueIdentifierService.TryGetAdjustedName(parameter, out adjustedParameterName)) 
            {
                Debug.Fail("parameter must be registered in identifier service");
            }
            Type parameterType = DetermineParameterType(parameter); 

            // make sure the variable name does not collide with any parameters to the method, or any 
            // existing variables (all registered in the service) 
            string variableName = uniqueIdentifierService.AdjustIdentifier(parameter.Name + "Parameter");
 
            // ObjectParameter variableName;
            // if (null != parameterName)
            // {
            //     variableName = new ObjectParameter("parameterName", adjustedParameterName); 
            // }
            // else 
            // { 
            //     variableName = new ObjectParameter("parameterName", typeof(parameterType));
            // } 
            method.Statements.Add(
                new CodeVariableDeclarationStatement(TypeReference.ForType(typeof(ObjectParameter)), variableName));
            CodeExpression variableReference = new CodeVariableReferenceExpression(variableName);
            CodeExpression parameterReference = new CodeVariableReferenceExpression(adjustedParameterName); 
            CodeStatement nullConstructor = new CodeAssignStatement(variableReference,
                new CodeObjectCreateExpression(TypeReference.ForType(typeof(ObjectParameter)), 
                new CodePrimitiveExpression(parameter.Name), 
                new CodeTypeOfExpression(TypeReference.ForType(parameterType))));
            CodeStatement valueConstructor = new CodeAssignStatement(variableReference, 
                new CodeObjectCreateExpression(TypeReference.ForType(typeof(ObjectParameter)),
                new CodePrimitiveExpression(parameter.Name),
                parameterReference));
            CodeExpression notNullCondition; 
            if (parameterType.IsValueType)
            { 
                // Value type parameters generate Nullable arguments (see CreateFunctionArgument). 
                // We call Nullable.HasValue to determine whether the argument passed in is null
                // (since null != nullableTypeInstance does not work in VB) 
                //
                // parameterReference.HasValue
                notNullCondition = new CodePropertyReferenceExpression(
                    parameterReference, 
                    "HasValue");
            } 
            else 
            {
                // use parameterReference != null 
                notNullCondition = new CodeBinaryOperatorExpression(
                    parameterReference,
                    CodeBinaryOperatorType.IdentityInequality,
                    NullExpression); 
            }
            method.Statements.Add( 
                new CodeConditionStatement( 
                    notNullCondition,
                    new CodeStatement[] { valueConstructor, }, 
                    new CodeStatement[] { nullConstructor, }
                )
            );
            return variableReference; 
        }
 
        private void CreateFunctionArgument(CodeMemberMethod method, UniqueIdentifierService uniqueIdentifierService, FunctionParameter parameter) 
        {
            // get type of parameter 
            Type clrType = DetermineParameterType(parameter);

            // parameters to stored procedures must be nullable
            CodeTypeReference argumentType = clrType.IsValueType ? TypeReference.NullableForType(clrType) : TypeReference.ForType(clrType); 
            string parameterName = uniqueIdentifierService.AdjustIdentifier(parameter.Name, parameter);
            CodeParameterDeclarationExpression codeParameter = new CodeParameterDeclarationExpression(argumentType, parameterName); 
            method.Parameters.Add(codeParameter); 
        }
 
        // requires: parameter type is constrained to be a scalar type
        // Determines CLR type for function parameter
        private static Type DetermineParameterType(FunctionParameter parameter)
        { 
            Debug.Assert(null != parameter && MetadataUtil.IsPrimitiveType(parameter.TypeUsage.EdmType),
                "validation must ensure only scalar type parameter are given"); 
 
            if (parameter.Mode != ParameterMode.In)
            { 
                // non input parameter must be treated as ObjectParameter instances so that the
                // value can be set asynchronously (after the method has yielded and the reader
                // has been consumed)
                return typeof(ObjectParameter); 
            }
 
            PrimitiveType parameterType = (PrimitiveType)parameter.TypeUsage.EdmType; 
            Type clrType = parameterType.ClrType;
            return clrType; 
        }

        /// 
        /// return a code expression for invoking OnContextCreated partial method 
        /// 
        private CodeMethodInvokeExpression OnContextCreatedCodeMethodInvokeExpression() 
        { 
            return (new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), _onContextCreatedString, new CodeExpression[] { }));
        } 

        /// 
        /// Returns the type specific SchemaElement
        ///  
        private new EntityContainer Item
        { 
            get 
            {
                return base.Item as EntityContainer; 
            }
        }

        #endregion 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK