EntityContainerEmitter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntityDesign / Design / System / Data / EntityModel / Emitters / EntityContainerEmitter.cs / 1 / 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; 


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 (Helper.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 (Helper.IsEntitySet(entitySetBase))
                { 
                    EntitySet set = (EntitySet)entitySetBase;
                    CodeMemberMethod codeProperty = CreateEntitySetAddObjectProperty(set);
                    typeDecl.Members.Add(codeProperty);
                } 
            }
 
            foreach (EdmFunction functionImport in Item.FunctionImports) 
            {
                // produce code for entity readers only at this point 
                if (functionImport.EntitySet != null)
                {
                    CodeMemberMethod functionMethod = CreateFunctionImportEntityReaderMethod(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; 
        }
 
        ///  
        /// 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 (Helper.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
            // 
            // private ObjectQuery _Customers = null; 

            CodeMemberField codeField = new CodeMemberField(); 
            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();
            codeProperty.Attributes = MemberAttributes.Final | GetEntitySetPropertyAccessibility(set);
            codeProperty.Name = set.Name; 
            codeProperty.HasGet = true;
            codeProperty.HasSet = false; 
 
            CodeTypeReference genericParameter = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType);
            codeProperty.Type = TypeReference.AdoFrameworkGenericClass("ObjectQuery", 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(), 
                                "CreateQuery",
                                new CodeTypeReference[] { genericParameter }
                            ),
                            new CodePrimitiveExpression("[" + set.Name + "]") 
                        )
                    ) 
                ) 
            );
 
            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(); 
            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 CreateFunctionImportEntityReaderMethod(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 && null != functionImport.EntitySet);

            CodeMemberMethod method = new CodeMemberMethod(); 
            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 = functionImport.ReturnParameter.TypeUsage.EdmType; 
            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 && TypeSemantics.IsPrimitiveType(parameter.TypeUsage), 
                "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; 


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 (Helper.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 (Helper.IsEntitySet(entitySetBase))
                { 
                    EntitySet set = (EntitySet)entitySetBase;
                    CodeMemberMethod codeProperty = CreateEntitySetAddObjectProperty(set);
                    typeDecl.Members.Add(codeProperty);
                } 
            }
 
            foreach (EdmFunction functionImport in Item.FunctionImports) 
            {
                // produce code for entity readers only at this point 
                if (functionImport.EntitySet != null)
                {
                    CodeMemberMethod functionMethod = CreateFunctionImportEntityReaderMethod(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; 
        }
 
        ///  
        /// 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 (Helper.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
            // 
            // private ObjectQuery _Customers = null; 

            CodeMemberField codeField = new CodeMemberField(); 
            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();
            codeProperty.Attributes = MemberAttributes.Final | GetEntitySetPropertyAccessibility(set);
            codeProperty.Name = set.Name; 
            codeProperty.HasGet = true;
            codeProperty.HasSet = false; 
 
            CodeTypeReference genericParameter = Generator.GetLeastPossibleQualifiedTypeReference(set.ElementType);
            codeProperty.Type = TypeReference.AdoFrameworkGenericClass("ObjectQuery", 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(), 
                                "CreateQuery",
                                new CodeTypeReference[] { genericParameter }
                            ),
                            new CodePrimitiveExpression("[" + set.Name + "]") 
                        )
                    ) 
                ) 
            );
 
            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(); 
            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 CreateFunctionImportEntityReaderMethod(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 && null != functionImport.EntitySet);

            CodeMemberMethod method = new CodeMemberMethod(); 
            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 = functionImport.ReturnParameter.TypeUsage.EdmType; 
            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 && TypeSemantics.IsPrimitiveType(parameter.TypeUsage), 
                "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