MappedMetaModel.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 / DLinq / Dlinq / Mapping / MappedMetaModel.cs / 1 / MappedMetaModel.cs

                            using System; 
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq.Expressions; 
using System.Reflection;
using System.Text; 
using System.Linq; 
using System.Data.Linq.Provider;
using System.Data.Linq.Mapping; 
using System.Data.Linq.SqlClient;
using System.Threading;
using LinqToSqlShared.Mapping;
 
namespace System.Data.Linq.Mapping {
 
    internal class MappedMetaModel : MetaModel { 
        ReaderWriterLock @lock = new ReaderWriterLock();
        MappingSource mappingSource; 
        Type contextType;
        Type providerType;
        DatabaseMapping mapping;
        HashSet modules; 
        Dictionary types;
        Dictionary metaTypes; 
        Dictionary metaTables; 
        Dictionary metaFunctions;
        bool fullyLoaded; 

        internal MappedMetaModel(MappingSource mappingSource, Type contextType, DatabaseMapping mapping) {
            this.mappingSource = mappingSource;
            this.contextType = contextType; 
            this.mapping = mapping;
            this.modules = new HashSet(); 
            this.modules.Add(this.contextType.Module); 
            this.metaTypes = new Dictionary();
            this.metaTables = new Dictionary(); 
            this.types = new Dictionary();
            // Provider type
            if (this.providerType == null && !String.IsNullOrEmpty(this.mapping.Provider)) {
                this.providerType = this.FindType(this.mapping.Provider, typeof(SqlProvider).Namespace); 
                if (this.providerType == null) {
                    throw Error.ProviderTypeNotFound(this.mapping.Provider); 
                } 
            }
            else if (this.providerType == null) { 
                this.providerType = typeof(SqlProvider);
            }
            this.Init();
        } 
        #region Initialization
        private void Init() { 
            if (!fullyLoaded) { 
                // The fullyLoaded state is required so that tools like
                // CreateDatabase can get a full view of all tables. 
                @lock.AcquireWriterLock(Timeout.Infinite);
                try {
                    if (!fullyLoaded) {
                        // Initialize static tables and functions. 
                        this.InitStaticTables();
                        this.InitFunctions(); 
                        fullyLoaded = true; 
                    }
                } 
                finally {
                    @lock.ReleaseWriterLock();
                }
            } 
        }
 
        private void InitStaticTables() { 
            this.InitStaticTableTypes();
            foreach (TableMapping tableMapping in this.mapping.Tables) { 
                Type rowType = this.FindType(tableMapping.RowType.Name);
                if (rowType == null) {
                    throw Error.CouldNotFindTypeFromMapping(tableMapping.RowType.Name);
                } 
                Type rootType = this.GetRootType(rowType, tableMapping.RowType);
                MetaTable table = new MappedTable(this, tableMapping, rootType); 
                foreach (MetaType mt in table.RowType.InheritanceTypes) { 
                    this.metaTypes.Add(mt.Type, mt);
                    this.metaTables.Add(mt.Type, table); 
                }
            }
        }
 
        private void InitStaticTableTypes() {
            for (Type type = this.contextType; type != typeof(DataContext); type = type.BaseType) { 
                FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); 
                foreach (FieldInfo fi in fields) {
                    Type ft = fi.FieldType; 
                    if (ft.IsGenericType && ft.GetGenericTypeDefinition() == typeof(Table<>)) {
                        Type rowType = ft.GetGenericArguments()[0];
                        if (!this.types.ContainsKey(rowType.Name)) {
                            this.types.Add(rowType.FullName, rowType); 
                            if (!this.types.ContainsKey(rowType.Name)) {
                                this.types.Add(rowType.Name, rowType); 
                            } 
                            this.modules.Add(rowType.Module);
                        } 
                    }
                }
                PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
                foreach (PropertyInfo pi in props) { 
                    Type pt = pi.PropertyType;
                    if (pt.IsGenericType && pt.GetGenericTypeDefinition() == typeof(Table<>)) { 
                        Type rowType = pt.GetGenericArguments()[0]; 
                        if (!this.types.ContainsKey(rowType.Name)) {
                            this.types.Add(rowType.FullName, rowType); 
                            if (!this.types.ContainsKey(rowType.Name)) {
                                this.types.Add(rowType.Name, rowType);
                            }
                            this.modules.Add(rowType.Module); 
                        }
                    } 
                } 
            }
        } 

        private void InitFunctions() {
            this.metaFunctions = new Dictionary();
            if (this.contextType != typeof(DataContext)) { 
                foreach (FunctionMapping fmap in this.mapping.Functions) {
                    MethodInfo method = this.GetMethod(fmap.MethodName); 
                    if (method == null) { 
                        throw Error.MethodCannotBeFound(fmap.MethodName);
                    } 
                    MappedFunction func = new MappedFunction(this, fmap, method);
                    this.metaFunctions.Add(new MetaPosition(method), func);

                    // pre-set all known function result types into metaType map 
                    foreach (MetaType rt in func.ResultRowTypes) {
                        foreach (MetaType it in rt.InheritanceTypes) { 
                            if (!this.metaTypes.ContainsKey(it.Type)) { 
                                this.metaTypes.Add(it.Type, it);
                            } 
                        }
                    }
                }
            } 
        }
        #endregion 
 
        public override MappingSource MappingSource {
            get { return this.mappingSource; } 
        }

        public override Type ContextType {
            get { return this.contextType; } 
        }
 
        public override string DatabaseName { 
            get { return this.mapping.DatabaseName; }
        } 

        public override Type ProviderType {
            get { return this.providerType; }
        } 

        public override IEnumerable GetTables() { 
            return this.metaTables.Values.Where(x => x != null).Distinct(); 
        }
 
        public override MetaTable GetTable(Type rowType) {
            if (rowType == null) {
                throw Error.ArgumentNull("rowType");
            } 
            MetaTable table = null;
            this.metaTables.TryGetValue(rowType, out table); 
            return table; 
        }
 
        public override MetaType GetMetaType(Type type) {
            if (type == null) {
                throw Error.ArgumentNull("type");
            } 
            MetaType mtype = null;
            @lock.AcquireReaderLock(Timeout.Infinite); 
            try { 
                if (this.metaTypes.TryGetValue(type, out mtype)) {
                    return mtype; 
                }
            }
            finally {
                @lock.ReleaseReaderLock(); 
            }
            @lock.AcquireWriterLock(Timeout.Infinite); 
            try { 
                if (!this.metaTypes.TryGetValue(type, out mtype)) {
                    // not known, so must be unmapped type 
                    mtype = new UnmappedType(this, type);
                    this.metaTypes.Add(type, mtype);
                }
            } 
            finally {
                @lock.ReleaseWriterLock(); 
            } 
            return mtype;
        } 

        public override MetaFunction GetFunction(MethodInfo method) {
            if (method == null) {
                throw new ArgumentNullException("method"); 
            }
            MetaFunction func = null; 
            this.metaFunctions.TryGetValue(new MetaPosition(method), out func); 
            return func;
        } 

        public override IEnumerable GetFunctions() {
            return this.metaFunctions.Values;
        } 

        private Type GetRootType(Type type, TypeMapping rootMapping) { 
            if (string.Compare(rootMapping.Name, type.Name, StringComparison.Ordinal) == 0 
                || string.Compare(rootMapping.Name, type.FullName, StringComparison.Ordinal) == 0
                || string.Compare(rootMapping.Name, type.AssemblyQualifiedName, StringComparison.Ordinal) == 0) 
                return type;
            if (type.BaseType != typeof(object)) {
                return this.GetRootType(type.BaseType, rootMapping);
            } 
            throw Error.UnableToResolveRootForType(type);
        } 
 
        private MethodInfo GetMethod(string name) {
            string typeName, methodName; 
            this.GetTypeAndMethod(name, out typeName, out methodName);
            Type type = this.FindType(typeName);
            if (type != null) {
                return type.GetMethod(methodName, BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic); 
            }
            return null; 
        } 

        private void GetTypeAndMethod(string name, out string typeName, out string methodName) { 
            int dotIndex = name.LastIndexOf(".", StringComparison.CurrentCulture);
            if (dotIndex > 0) {
                typeName = name.Substring(0, dotIndex);
                methodName = name.Substring(dotIndex + 1); 
            }
            else { 
                typeName = this.contextType.FullName; 
                methodName = name;
            } 
        }

        internal Type FindType(string name) {
            return this.FindType(name, this.contextType.Namespace); 
        }
 
        internal Type FindType(string name, string defaultNamespace) { 
            Type result = null;
            string name2 = null; 
            @lock.AcquireReaderLock(Timeout.Infinite);
            try {
                if (this.types.TryGetValue(name, out result)) {
                    return result; 
                }
                name2 = name.Contains(".") ? null : defaultNamespace + "." + name; 
                if (name2 != null && this.types.TryGetValue(name2, out result)) { 
                    return result;
                } 
            }
            finally {
                @lock.ReleaseReaderLock();
            } 
            // don't block anyone while we search for the correct type
            Type foundResult = this.SearchForType(name); 
 
            if (foundResult == null && name2 != null) {
                foundResult = this.SearchForType(name2); 
            }
            if (foundResult != null) {
                @lock.AcquireWriterLock(Timeout.Infinite);
                try { 
                    if (this.types.TryGetValue(name, out result)) {
                        return result; 
                    } 
                    this.types.Add(name, foundResult);
                    return foundResult; 
                }
                finally {
                    @lock.ReleaseWriterLock();
                } 
            }
            return null; 
        } 

        private Type SearchForType(string name) { 
            // Try search for type using case sensitive.
            Type type = SearchForType(name, false);
            if (type != null) {
                return type; 
            }
 
            // Try search for type using case in-sensitive. 
            return SearchForType(name, true);
        } 

        private Type SearchForType(string name, bool ignoreCase) {
            // first try default system lookup
            Type type = Type.GetType(name, false, ignoreCase); 
            if (type != null) {
                return type; 
            } 

            // try all known modules (modules that other statically known types were found in) 
            foreach (Module module in this.modules) {
                type = module.GetType(name, false, ignoreCase);
                if (type != null) {
                    return type; 
                }
            } 
 
            // try all loaded modules (is there a better way?)
            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) { 
                foreach (Module module in a.GetLoadedModules()) {
                    type = module.GetType(name, false, ignoreCase);
                    if (type != null) {
                        return type; 
                    }
                } 
            } 

            return null; 
        }
    }

    internal sealed class MappedTable : MetaTable { 
        MappedMetaModel model;
        TableMapping mapping; 
        MetaType rowType; 
        bool hasMethods;
        MethodInfo insertMethod; 
        MethodInfo updateMethod;
        MethodInfo deleteMethod;

        internal MappedTable(MappedMetaModel model, TableMapping mapping, Type rowType) { 
            this.model = model;
            this.mapping = mapping; 
            this.rowType = new MappedRootType(model, this, mapping.RowType, rowType); 
        }
        public override MetaModel Model { 
            get { return this.model; }
        }
        public override string TableName {
            get { return this.mapping.TableName; } 
        }
        public override MetaType RowType { 
            get { return this.rowType; } 
        }
        public override MethodInfo InsertMethod { 
            get {
                this.InitMethods();
                return this.insertMethod;
            } 
        }
        public override MethodInfo UpdateMethod { 
            get { 
                this.InitMethods();
                return this.updateMethod; 
            }
        }
        public override MethodInfo DeleteMethod {
            get { 
                this.InitMethods();
                return this.deleteMethod; 
            } 
        }
        private void InitMethods() { 
            if (!this.hasMethods) {
                this.insertMethod = MethodFinder.FindMethod(
                    this.model.ContextType,
                    "Insert" + rowType.Name, 
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    new Type[] { rowType.Type } 
                    ); 
                this.updateMethod = MethodFinder.FindMethod(
                    this.model.ContextType, 
                    "Update" + rowType.Name,
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    new Type[] { rowType.Type }
                    ); 
                this.deleteMethod = MethodFinder.FindMethod(
                    this.model.ContextType, 
                    "Delete" + rowType.Name, 
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    new Type[] { rowType.Type } 
                    );
                this.hasMethods = true;
            }
        } 
    }
 
    internal sealed class MappedRootType : MappedType { 
        Dictionary derivedTypes;
        Dictionary inheritanceCodes; 
        ReadOnlyCollection inheritanceTypes;
        MetaType inheritanceDefault;
        bool hasInheritance;
 
        public MappedRootType(MappedMetaModel model, MappedTable table, TypeMapping typeMapping, Type type)
            : base(model, table, typeMapping, type, null) { 
            if (typeMapping == null) 
                throw Error.ArgumentNull("typeMapping");
 
            if (typeMapping.InheritanceCode != null || typeMapping.DerivedTypes.Count > 0) {
                if (this.Discriminator == null) {
                    throw Error.NoDiscriminatorFound(type.Name);
                } 
                this.hasInheritance = true;
                if (!MappingSystem.IsSupportedDiscriminatorType(this.Discriminator.Type)) { 
                    throw Error.DiscriminatorClrTypeNotSupported(this.Discriminator.DeclaringType.Name, this.Discriminator.Name, this.Discriminator.Type); 
                }
                this.derivedTypes = new Dictionary(); 
                this.inheritanceCodes = new Dictionary();
                this.InitInheritedType(typeMapping, this);
            }
 
            if (this.inheritanceDefault == null && (this.inheritanceCode != null || this.inheritanceCodes != null && this.inheritanceCodes.Count > 0))
                throw Error.InheritanceHierarchyDoesNotDefineDefault(type); 
 
            if (this.derivedTypes != null) {
                this.inheritanceTypes = this.derivedTypes.Values.ToList().AsReadOnly(); 
            }
            else {
                this.inheritanceTypes = new MetaType[] { this }.ToList().AsReadOnly();
            } 

            this.Validate(); 
        } 

        private void Validate() { 
            Dictionary memberToColumn = new Dictionary();
            foreach (MetaType type in this.InheritanceTypes) {
                // NB: Table node in XML can have only one Type node -- enforced by XSD
 
                foreach (MetaDataMember mem in type.PersistentDataMembers) {
                    if (mem.IsDeclaredBy(type)) { 
                        if (mem.IsDiscriminator && !this.HasInheritance) { 
                            throw Error.NonInheritanceClassHasDiscriminator(type);
                        } 
                        if (!mem.IsAssociation) {
                            // validate that no database column is mapped twice
                            if (!string.IsNullOrEmpty(mem.MappedName)) {
                                string column; 
                                object dn = InheritanceRules.DistinguishedMemberName(mem.Member);
                                if (memberToColumn.TryGetValue(dn, out column)) { 
                                    if (column != mem.MappedName) { 
                                        throw Error.MemberMappedMoreThanOnce(mem.Member.Name);
                                    } 
                                }
                                else {
                                    memberToColumn.Add(dn, mem.MappedName);
                                } 
                            }
                        } 
                    } 
                }
            } 
        }

        private MetaType InitDerivedTypes(TypeMapping typeMap) {
            Type type = ((MappedMetaModel)Model).FindType(typeMap.Name); 
            if (type == null)
                throw Error.CouldNotFindRuntimeTypeForMapping(typeMap.Name); 
            MappedType rowType = new MappedType(this.Model, this.Table, typeMap, type, this); 
            return this.InitInheritedType(typeMap, rowType);
        } 

        private MetaType InitInheritedType(TypeMapping typeMap, MappedType type) {
            this.derivedTypes.Add(type.Type, type);
 
            if (typeMap.InheritanceCode != null) { // Mapping with no inheritance code: For example, an unmapped intermediate class in a hierarchy.
                if (this.Discriminator == null) 
                    throw Error.NoDiscriminatorFound(type.Name); 

                if (type.Type.IsAbstract) 
                    throw Error.AbstractClassAssignInheritanceDiscriminator(type.Type);

                object keyValue = DBConvert.ChangeType(typeMap.InheritanceCode, this.Discriminator.Type);
                foreach (object d in inheritanceCodes.Keys) { 
                    // if the keys are equal, or if they are both strings containing only spaces
                    // they are considered equal 
                    if ((keyValue.GetType() == typeof(string) && ((string)keyValue).Trim().Length == 0 && 
                        d.GetType() == typeof(string) && ((string)d).Trim().Length == 0) ||
                        object.Equals(d, keyValue)) { 
                        throw Error.InheritanceCodeUsedForMultipleTypes(keyValue);
                    }
                }
                if (type.inheritanceCode != null) 
                    throw Error.InheritanceTypeHasMultipleDiscriminators(type);
                type.inheritanceCode = keyValue; 
                this.inheritanceCodes.Add(keyValue, type); 
                if (typeMap.IsInheritanceDefault) {
                    if (this.inheritanceDefault != null) 
                        throw Error.InheritanceTypeHasMultipleDefaults(type);
                    this.inheritanceDefault = type;
                }
            } 

            // init sub-inherited types 
            foreach (TypeMapping tm in typeMap.DerivedTypes) { 
                this.InitDerivedTypes(tm);
            } 

            return type;
        }
 
        public override bool HasInheritance {
            get { return this.hasInheritance; } 
        } 

        public override bool HasInheritanceCode { 
            get { return this.InheritanceCode != null; }
        }

        public override ReadOnlyCollection InheritanceTypes { 
            get { return this.inheritanceTypes; }
        } 
 
        public override MetaType GetInheritanceType(Type type) {
            if (type == this.Type) 
                return this;
            MetaType metaType = null;
            if (this.derivedTypes != null) {
                this.derivedTypes.TryGetValue(type, out metaType); 
            }
            return metaType; 
        } 

        public override MetaType InheritanceDefault { 
            get { return this.inheritanceDefault; }
        }
    }
 
    internal class MappedType : MetaType {
        MetaModel model; 
        MetaTable table; 
        Type type;
        TypeMapping typeMapping; 
        Dictionary dataMemberMap;
        ReadOnlyCollection dataMembers;
        ReadOnlyCollection persistentDataMembers;
        ReadOnlyCollection identities; 
        MetaDataMember dbGeneratedIdentity;
        MetaDataMember version; 
        MetaDataMember discriminator; 
        MetaType inheritanceRoot;
        bool inheritanceBaseSet; 
        MetaType inheritanceBase;
        internal object inheritanceCode;
        ReadOnlyCollection derivedTypes;
        ReadOnlyCollection associations; 
        bool hasMethods;
        bool hasAnyLoadMethod; 
        bool hasAnyValidateMethod; 
        MethodInfo onLoadedMethod;
        MethodInfo onValidateMethod; 

        object locktarget = new object(); // Hold locks on private object rather than public MetaType.

        internal MappedType(MetaModel model, MetaTable table, TypeMapping typeMapping, Type type, MetaType inheritanceRoot) { 
            this.model = model;
            this.table = table; 
            this.typeMapping = typeMapping; 
            this.type = type;
            this.inheritanceRoot = inheritanceRoot != null ? inheritanceRoot : this; 
            this.InitDataMembers();

            this.identities = this.dataMembers.Where(m => m.IsPrimaryKey).ToList().AsReadOnly();
            this.persistentDataMembers = this.dataMembers.Where(m => m.IsPersistent).ToList().AsReadOnly(); 
        }
        #region Initialization 
        private void ValidatePrimaryKeyMember(MetaDataMember mm) { 
            //if the type is a sub-type, no member in the type can be primary key
            if (mm.IsPrimaryKey && this.inheritanceRoot != this && mm.Member.DeclaringType == this.type) { 
                throw (Error.PrimaryKeyInSubTypeNotSupported(this.type.Name, mm.Name));
            }
        }
 
        private void InitMethods() {
            if (!this.hasMethods) { 
                this.onLoadedMethod = MethodFinder.FindMethod( 
                    this.Type,
                    "OnLoaded", 
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    Type.EmptyTypes,
                    false
                    ); 
                this.onValidateMethod = MethodFinder.FindMethod(
                    this.Type, 
                    "OnValidate", 
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    new[] { typeof(ChangeAction) }, 
                    false
                    );

                this.hasAnyLoadMethod = (this.onLoadedMethod != null) || (this.InheritanceBase != null && this.InheritanceBase.HasAnyLoadMethod); 
                this.hasAnyValidateMethod = (this.onValidateMethod != null) || (this.InheritanceBase != null && this.InheritanceBase.HasAnyValidateMethod);
 
                this.hasMethods = true; 
            }
        } 

        private void InitDataMembers() {
            if (this.dataMembers == null) {
                Dictionary map = new Dictionary(); 
                List dMembers = new List();
                int ordinal = 0; 
                BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; 

                // Map of valid mapped names. 
                Dictionary names = new Dictionary();
                Type currentType = this.type;
                for (TypeMapping tm = this.typeMapping; tm != null; tm = tm.BaseType) {
                    foreach (MemberMapping mmap in tm.Members) { 
                        names[mmap.MemberName + ":" + currentType.Name] = mmap;
                    } 
                    currentType = currentType.BaseType; 
                }
 
                HashSet namesSeen = new HashSet(); // Keep track of which names from the mapping file have been seen.
                FieldInfo[] fis = TypeSystem.GetAllFields(this.type, flags).ToArray();
                if (fis != null) {
                    foreach (FieldInfo fi in fis) { 
                        MemberMapping mmap;
                        string name = fi.Name + ":" + fi.DeclaringType.Name; 
                        if (names.TryGetValue(name, out mmap)) { 
                            namesSeen.Add(name);
                            object dn = InheritanceRules.DistinguishedMemberName(fi); 
                            MetaDataMember mm;
                            if (!map.TryGetValue(dn, out mm)) {
                                mm = new MappedDataMember(this, fi, mmap, ordinal);
                                map.Add(InheritanceRules.DistinguishedMemberName(mm.Member), mm); 
                                dMembers.Add(mm);
                                this.InitSpecialMember(mm); 
                            } 
                            ValidatePrimaryKeyMember(mm);
                            ordinal++; 
                        }
                    }
                }
 
                PropertyInfo[] pis = TypeSystem.GetAllProperties(this.type, flags).ToArray();
                if (pis != null) { 
                    foreach (PropertyInfo pi in pis) { 
                        MemberMapping mmap;
                        string name = pi.Name + ":" + pi.DeclaringType.Name; 
                        if (names.TryGetValue(name, out mmap)) {
                            namesSeen.Add(name);
                            MetaDataMember mm;
                            object dn = InheritanceRules.DistinguishedMemberName(pi); 
                            if (!map.TryGetValue(dn, out mm)) {
                                mm = new MappedDataMember(this, pi, mmap, ordinal); 
                                map.Add(InheritanceRules.DistinguishedMemberName(mm.Member), mm); 
                                dMembers.Add(mm);
                                this.InitSpecialMember(mm); 
                            }
                            ValidatePrimaryKeyMember(mm);
                            ordinal++;
                        } 
                    }
                } 
 
                this.dataMembers = dMembers.AsReadOnly();
                this.dataMemberMap = map; 

                // Finally, make sure that all types in the mapping file were consumed.
                foreach(string name in namesSeen) {
                    names.Remove(name); 
                }
                foreach(var orphan in names) { 
                    Type aboveRoot = inheritanceRoot.Type.BaseType; 
                    while (aboveRoot!=null) {
                        foreach(MemberInfo mi in aboveRoot.GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { 
                            if(String.Compare(mi.Name, orphan.Value.MemberName, StringComparison.Ordinal)==0) {
                                throw Error.MappedMemberHadNoCorrespondingMemberInType(orphan.Value.MemberName, type.Name);
                            }
                        } 
                        aboveRoot = aboveRoot.BaseType;
                    } 
                } 
            }
        } 
        private void InitSpecialMember(MetaDataMember mm) {
            // Can only have one auto gen member that is also an identity member,
            // except if that member is a computed column (since they are implicitly auto gen)
            if (mm.IsDbGenerated && mm.IsPrimaryKey && string.IsNullOrEmpty(mm.Expression)) { 
                if (this.dbGeneratedIdentity != null) {
                    throw Error.TwoMembersMarkedAsPrimaryKeyAndDBGenerated(mm.Member, this.dbGeneratedIdentity.Member); 
                } 
                this.dbGeneratedIdentity = mm;
            } 
            if (mm.IsPrimaryKey && !MappingSystem.IsSupportedIdentityType(mm.Type))
            {
                throw Error.IdentityClrTypeNotSupported(mm.DeclaringType, mm.Name, mm.Type);
            } 
            if (mm.IsVersion) {
                if (this.version != null) { 
                    throw Error.TwoMembersMarkedAsRowVersion(mm.Member, this.version.Member); 
                }
                this.version = mm; 
            }
            if (mm.IsDiscriminator) {
                if (this.discriminator != null) {
                    if (!InheritanceRules.AreSameMember(this.discriminator.Member, mm.Member)) { 
                        throw Error.TwoMembersMarkedAsInheritanceDiscriminator(mm.Member, this.discriminator.Member);
                    } 
                } 
                else {
                    this.discriminator = mm; 
                }
            }
        }
        #endregion 
        public override MetaModel Model {
            get { return this.model; } 
        } 
        public override MetaTable Table {
            get { return this.table; } 
        }
        public override Type Type {
            get { return this.type; }
        } 
        public override string Name {
            get { return this.type.Name; } 
        } 
        public override bool IsEntity {
            get { 
                if (this.table != null) {
                    return table.RowType.IdentityMembers.Count > 0;
                }
                return false; 
            }
 
        } 
        public override bool CanInstantiate {
            get { return !this.type.IsAbstract && (this == this.InheritanceRoot || this.HasInheritanceCode); } 
        }
        public override MetaDataMember DBGeneratedIdentityMember {
            get { return this.dbGeneratedIdentity; }
        } 
        public override MetaDataMember VersionMember {
            get { return this.version; } 
        } 
        public override MetaDataMember Discriminator {
            get { return this.discriminator; } 
        }
        public override bool HasUpdateCheck {
            get {
                foreach (MetaDataMember member in this.PersistentDataMembers) { 
                    if (member.UpdateCheck != UpdateCheck.Never) {
                        return true; 
                    } 
                }
                return false; 
            }
        }
        public override bool HasInheritance {
            get { return this.inheritanceRoot.HasInheritance; } 
        }
        public override object InheritanceCode { 
            get { return this.inheritanceCode; } 
        }
        public override bool HasInheritanceCode { 
            get { return this.InheritanceCode != null; }
        }
        public override bool IsInheritanceDefault {
            get { return this.InheritanceDefault == this; } 
        }
        public override MetaType InheritanceDefault { 
            get { 
                if (this.inheritanceRoot == this)
                    throw Error.CannotGetInheritanceDefaultFromNonInheritanceClass(); 
                return this.InheritanceRoot.InheritanceDefault;
            }
        }
        public override MetaType InheritanceRoot { 
            get { return this.inheritanceRoot; }
        } 
        public override MetaType InheritanceBase { 
            get {
                // LOCKING: Cannot initialize at construction 
                if (!this.inheritanceBaseSet && this.inheritanceBase == null) {
                    lock (this.locktarget) {
                        if (this.inheritanceBase == null) {
                            this.inheritanceBase = InheritanceBaseFinder.FindBase(this); 
                            this.inheritanceBaseSet = true;
                        } 
                    } 
                }
                return this.inheritanceBase; 
            }
        }
        public override ReadOnlyCollection InheritanceTypes {
            get { return this.inheritanceRoot.InheritanceTypes; } 
        }
        public override ReadOnlyCollection DerivedTypes { 
            get { 
                // LOCKING: Cannot initialize at construction because derived types
                // won't exist yet. 
                if (this.derivedTypes == null) {
                    lock (this.locktarget) {
                        if (this.derivedTypes == null) {
                            List dTypes = new List(); 
                            foreach (MetaType mt in this.InheritanceTypes) {
                                if (mt.Type.BaseType == this.type) 
                                    dTypes.Add(mt); 
                            }
                            this.derivedTypes = dTypes.AsReadOnly(); 
                        }
                    }
                }
                return this.derivedTypes; 
            }
        } 
        public override MetaType GetInheritanceType(Type inheritanceType) { 
            foreach (MetaType mt in this.InheritanceTypes)
                if (mt.Type == inheritanceType) 
                    return mt;
            return null;
        }
        public override MetaType GetTypeForInheritanceCode(object key) { 
            if (this.InheritanceRoot.Discriminator.Type == typeof(string)) {
                string skey = (string)key; 
                foreach (MetaType mt in this.InheritanceRoot.InheritanceTypes) { 
                    if (string.Compare((string)mt.InheritanceCode, skey, StringComparison.OrdinalIgnoreCase) == 0)
                        return mt; 
                }
            }
            else {
                foreach (MetaType mt in this.InheritanceRoot.InheritanceTypes) { 
                    if (object.Equals(mt.InheritanceCode, key))
                        return mt; 
                } 
            }
            return null; 
        }
        public override ReadOnlyCollection DataMembers {
            get { return this.dataMembers; }
        } 
        public override ReadOnlyCollection PersistentDataMembers {
            get { return this.persistentDataMembers; } 
        } 
        public override ReadOnlyCollection IdentityMembers {
            get { return this.identities; } 
        }
        public override ReadOnlyCollection Associations {
            get {
                // LOCKING: Associations are late-expanded so that cycles are broken. 
                if (this.associations == null) {
                    lock (this.locktarget) { 
                        if (this.associations == null) { 
                            this.associations = this.dataMembers.Where(m => m.IsAssociation).Select(m => m.Association).ToList().AsReadOnly();
                        } 
                    }
                }
                return this.associations;
            } 
        }
        public override MetaDataMember GetDataMember(MemberInfo mi) { 
            if (mi == null) 
                throw Error.ArgumentNull("mi");
            MetaDataMember mm; 
            if (this.dataMemberMap.TryGetValue(InheritanceRules.DistinguishedMemberName(mi), out mm)) {
                return mm;
            } else {
                if (mi.DeclaringType.IsInterface) { 
                    throw Error.MappingOfInterfacesMemberIsNotSupported(mi.DeclaringType.Name, mi.Name);
                } else { //the member is not mapped in the base class 
                    throw Error.UnmappedClassMember(mi.DeclaringType.Name, mi.Name); 
                }
            } 
        }

        public override MethodInfo OnLoadedMethod {
            get { 
                this.InitMethods();
                return this.onLoadedMethod; 
            } 
        }
 
        public override MethodInfo OnValidateMethod {
            get {
                this.InitMethods();
                return this.onValidateMethod; 
            }
        } 
        public override bool HasAnyValidateMethod { 
            get {
                this.InitMethods(); 
                return this.hasAnyValidateMethod;
            }
        }
        public override bool HasAnyLoadMethod { 
            get {
                this.InitMethods(); 
                return this.hasAnyLoadMethod; 
            }
        } 

        public override string ToString() {
            return this.Name;
        } 
    }
 
    internal sealed class MappedDataMember : MetaDataMember { 
        MetaType declaringType;
        MemberInfo member; 
        MemberInfo storageMember;
        int ordinal;
        Type type;
        bool hasAccessors; 
        MetaAccessor accPublic;
        MetaAccessor accPrivate; 
        MetaAccessor accDefValue; 
        MetaAccessor accDefSource;
        MemberMapping memberMap; 
        MappedAssociation assoc;
        bool isNullableType;
        bool isDeferred;
        bool isPrimaryKey; 
        bool isVersion;
        bool isDBGenerated; 
        bool isDiscriminator; 
        bool canBeNull = true;
        string dbType; 
        string expression;
        string mappedName;
        UpdateCheck updateCheck = UpdateCheck.Never;
        AutoSync autoSync = AutoSync.Never; 
        object locktarget = new object(); // Hold locks on private object rather than public MetaType.
        bool hasLoadMethod; 
        MethodInfo loadMethod; 

        internal MappedDataMember(MetaType declaringType, MemberInfo mi, MemberMapping map, int ordinal) { 
            this.declaringType = declaringType;
            this.member = mi;
            this.ordinal = ordinal;
            this.type = TypeSystem.GetMemberType(mi); 
            this.isNullableType = TypeSystem.IsNullableType(this.type);
            this.memberMap = map; 
            if (this.memberMap != null && this.memberMap.StorageMemberName != null) { 
                MemberInfo[] mis = mi.DeclaringType.GetMember(this.memberMap.StorageMemberName, BindingFlags.Instance | BindingFlags.NonPublic);
                if (mis == null || mis.Length != 1) { 
                    throw Error.BadStorageProperty(this.memberMap.StorageMemberName, mi.DeclaringType, mi.Name);
                }
                this.storageMember = mis[0];
            } 
            Type storageType = this.storageMember != null ? TypeSystem.GetMemberType(this.storageMember) : this.type;
            this.isDeferred = IsDeferredType(storageType); 
            ColumnMapping cmap = map as ColumnMapping; 
            if (cmap != null && cmap.IsDbGenerated && cmap.IsPrimaryKey) {
                // auto-gen identities must be synced on insert 
                if ((cmap.AutoSync != AutoSync.Default) && (cmap.AutoSync != AutoSync.OnInsert)) {
                    throw Error.IncorrectAutoSyncSpecification(mi.Name);
                }
            } 
            if (cmap != null) {
                this.isPrimaryKey = cmap.IsPrimaryKey; 
                this.isVersion = cmap.IsVersion; 
                this.isDBGenerated = cmap.IsDbGenerated || !string.IsNullOrEmpty(cmap.Expression) || this.isVersion;
                this.isDiscriminator = cmap.IsDiscriminator; 
                this.canBeNull = cmap.CanBeNull == null ? this.isNullableType || !this.type.IsValueType : (bool)cmap.CanBeNull;
                this.dbType = cmap.DbType;
                this.expression = cmap.Expression;
                this.updateCheck = cmap.UpdateCheck; 
                // auto-gen keys are always and only synced on insert
                if (this.IsDbGenerated && this.IsPrimaryKey) { 
                    this.autoSync = AutoSync.OnInsert; 
                }
                else if (cmap.AutoSync != AutoSync.Default) { 
                    // if the user has explicitly set it, use their value
                    this.autoSync = cmap.AutoSync;
                }
                else if (this.IsDbGenerated) { 
                    // database generated members default to always
                    this.autoSync = AutoSync.Always; 
                } 
            }
            this.mappedName = this.memberMap.DbName != null ? this.memberMap.DbName : this.member.Name; 
        }
        private void InitAccessors() {
            if (!this.hasAccessors) {
                lock (this.locktarget) { 
                    if (!this.hasAccessors) {
                        if (this.storageMember != null) { 
                            this.accPrivate = MakeMemberAccessor(this.member.ReflectedType, this.storageMember, null); 
                            if (this.isDeferred) {
                                MakeDeferredAccessors(this.member.ReflectedType, this.accPrivate, out this.accPrivate, out this.accDefValue, out this.accDefSource); 
                            }
                            this.accPublic = MakeMemberAccessor(this.member.ReflectedType, this.member, this.accPrivate);
                        }
                        else { 
                            this.accPublic = this.accPrivate = MakeMemberAccessor(this.member.ReflectedType, this.member, null);
                            if (this.isDeferred) { 
                                MakeDeferredAccessors(this.member.ReflectedType, this.accPrivate, out this.accPrivate, out this.accDefValue, out this.accDefSource); 
                            }
                        } 
                        this.hasAccessors = true;
                    }
                }
            } 
        }
        public override MetaType DeclaringType { 
            get { return this.declaringType; } 
        }
        public override bool IsDeclaredBy(MetaType metaType) { 
            if (metaType == null) {
                throw Error.ArgumentNull("metaType");
            }
            return metaType.Type == this.member.DeclaringType; 
        }
        public override MemberInfo Member { 
            get { return this.member; } 
        }
        public override MemberInfo StorageMember { 
            get { return this.storageMember; }
        }
        public override string Name {
            get { return this.member.Name; } 
        }
        public override int Ordinal { 
            get { return this.ordinal; } 
        }
        public override Type Type { 
            get { return this.type; }
        }
        public override MetaAccessor MemberAccessor {
            get { 
                this.InitAccessors();
                return this.accPublic; 
            } 
        }
        public override MetaAccessor StorageAccessor { 
            get {
                this.InitAccessors();
                return this.accPrivate;
            } 
        }
        public override MetaAccessor DeferredValueAccessor { 
            get { 
                this.InitAccessors();
                return this.accDefValue; 
            }
        }
        public override MetaAccessor DeferredSourceAccessor {
            get { 
                this.InitAccessors();
                return this.accDefSource; 
            } 
        }
        public override bool IsDeferred { 
            get { return this.isDeferred; }
        }
        public override bool IsPersistent {
            get { return this.memberMap != null; } 
        }
        public override bool IsAssociation { 
            get { return this.memberMap is AssociationMapping; } 
        }
        public override bool IsPrimaryKey { 
            get { return this.isPrimaryKey; }
        }
        /// 
        /// Returns true if the member is explicitly marked as auto gen, or if the 
        /// member is computed or generated by the database server.
        ///  
        public override bool IsDbGenerated { 
            get { return this.isDBGenerated; }
        } 
        public override bool IsVersion {
            get { return this.isVersion; }
        }
        public override bool IsDiscriminator { 
            get { return this.isDiscriminator; }
        } 
        public override bool CanBeNull { 
            get { return this.canBeNull; }
        } 
        public override string DbType {
            get { return this.dbType; }
        }
        public override string Expression { 
            get { return this.expression; }
        } 
        public override string MappedName { 
            get { return this.mappedName; }
        } 
        public override UpdateCheck UpdateCheck {
            get { return this.updateCheck; }
        }
        public override AutoSync AutoSync { 
            get { return this.autoSync; }
        } 
        public override MetaAssociation Association { 
            get {
                if (this.IsAssociation) { 
                    // LOCKING: This deferral isn't an optimization. It can't be done in the constructor
                    // because there may be loops in the association graph.
                    if (this.assoc == null) {
                        lock (this.locktarget) { 
                            if (this.assoc == null) {
                                this.assoc = new MappedAssociation(this, (AssociationMapping)this.memberMap); 
                            } 
                        }
                    } 
                }
                return this.assoc;
            }
        } 
        public override MethodInfo LoadMethod {
            get { 
                if (this.hasLoadMethod == false && this.IsDeferred) { 
                    // defer searching for this access method until we really need to know
                    this.loadMethod = MethodFinder.FindMethod( 
                        ((MappedMetaModel)this.declaringType.Model).ContextType,
                        "Load" + this.member.Name,
                        BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                        new Type[] { this.DeclaringType.Type } 
                        );
                    this.hasLoadMethod = true; 
                } 
                return this.loadMethod;
            } 
        }
        private bool IsDeferredType(Type clrType) {
            if (clrType == null || clrType == typeof(object)) {
                return false; 
            }
            if (clrType.IsGenericType) { 
                Type gtype = clrType.GetGenericTypeDefinition(); 
                return gtype == typeof(Link<>) ||
                    typeof(EntitySet<>).IsAssignableFrom(gtype) || 
                    typeof(EntityRef<>).IsAssignableFrom(gtype) ||
                    IsDeferredType(clrType.BaseType);
            }
            return false; 
        }
        private static MetaAccessor MakeMemberAccessor(Type accessorType, MemberInfo mi, MetaAccessor storage) { 
            FieldInfo fi = mi as FieldInfo; 
            MetaAccessor acc = null;
            if (fi != null) { 
                acc = FieldAccessor.Create(accessorType, fi);
            }
            else {
                PropertyInfo pi = (PropertyInfo)mi; 
                acc = PropertyAccessor.Create(accessorType, pi, storage);
            } 
            return acc; 
        }
        private static void MakeDeferredAccessors( 
            Type declaringType, MetaAccessor accessor,
            out MetaAccessor accessorValue, out MetaAccessor accessorDeferredValue, out MetaAccessor accessorDeferredSource
            ) {
            if (accessor.Type.IsGenericType) { 
                Type gtype = accessor.Type.GetGenericTypeDefinition();
                Type itemType = accessor.Type.GetGenericArguments()[0]; 
                if (gtype == typeof(Link<>)) { 
                    accessorValue = CreateAccessor(typeof(LinkValueAccessor<,>).MakeGenericType(declaringType, itemType), accessor);
                    accessorDeferredValue = CreateAccessor(typeof(LinkDefValueAccessor<,>).MakeGenericType(declaringType, itemType), accessor); 
                    accessorDeferredSource = CreateAccessor(typeof(LinkDefSourceAccessor<,>).MakeGenericType(declaringType, itemType), accessor);
                    return;
                }
                else if (typeof(EntityRef<>).IsAssignableFrom(gtype)) { 
                    accessorValue = CreateAccessor(typeof(EntityRefValueAccessor<,>).MakeGenericType(declaringType, itemType), accessor);
                    accessorDeferredValue = CreateAccessor(typeof(EntityRefDefValueAccessor<,>).MakeGenericType(declaringType, itemType), accessor); 
                    accessorDeferredSource = CreateAccessor(typeof(EntityRefDefSourceAccessor<,>).MakeGenericType(declaringType, itemType), accessor); 
                    return;
                } 
                else if (typeof(EntitySet<>).IsAssignableFrom(gtype)) {
                    accessorValue = CreateAccessor(typeof(EntitySetValueAccessor<,>).MakeGenericType(declaringType, itemType), accessor);
                    accessorDeferredValue = CreateAccessor(typeof(EntitySetDefValueAccessor<,>).MakeGenericType(declaringType, itemType), accessor);
                    accessorDeferredSource = CreateAccessor(typeof(EntitySetDefSourceAccessor<,>).MakeGenericType(declaringType, itemType), accessor); 
                    return;
                } 
            } 
            throw Error.UnhandledDeferredStorageType(accessor.Type);
        } 
        private static MetaAccessor CreateAccessor(Type accessorType, params object[] args) {
            return (MetaAccessor)Activator.CreateInstance(accessorType, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, args, null);
        }
    } 

    internal class MappedAssociation : MetaAssociationImpl { 
        MappedDataMember thisMember; 
        MetaDataMember otherMember;
        MetaType otherType; 
        ReadOnlyCollection thisKey;
        ReadOnlyCollection otherKey;
        bool isMany;
        bool isForeignKey; 
        bool isNullable;
        bool thisKeyIsPrimaryKey; 
        bool otherKeyIsPrimaryKey; 
        AssociationMapping assocMap;
 
        internal MappedAssociation(MappedDataMember mm, AssociationMapping assocMap) {
            this.thisMember = mm;
            this.assocMap = assocMap;
            this.Init(); 
            this.InitOther();
            //validate the number of ThisKey columns is the same as the number of OtherKey columns 
            if (this.thisKey.Count != this.otherKey.Count && this.thisKey.Count > 0 && this.otherKey.Count > 0) { 
                throw Error.MismatchedThisKeyOtherKey(thisMember.Name, thisMember.DeclaringType.Name);
            } 
        }
        #region Initialization
        private void Init() {
            this.isMany = TypeSystem.IsSequenceType(this.thisMember.Type); 
            this.thisKey = (this.assocMap.ThisKey != null)
                ? MakeKeys(this.thisMember.DeclaringType, this.assocMap.ThisKey) 
                : this.thisMember.DeclaringType.IdentityMembers; 
            // this association refers to the parent if thisKey is not our own identity
            this.thisKeyIsPrimaryKey = AreEqual(this.thisKey, this.thisMember.DeclaringType.IdentityMembers); 
            this.isForeignKey = this.assocMap.IsForeignKey;

            // if any key members are not nullable, the association is not nullable
            this.isNullable = true; 
            foreach (MetaDataMember mm in this.thisKey) {
                if (mm == null) 
                    throw Error.UnexpectedNull("MetaDataMember"); 

                if (!mm.CanBeNull) { 
                    this.isNullable = false;
                    break;
                }
            } 

            // validate DeleteOnNull specification 
            if (assocMap.DeleteOnNull == true) { 
                if (!(isForeignKey && !isMany && !isNullable)) {
                    throw Error.InvalidDeleteOnNullSpecification(thisMember); 
                }
            }
        }
        private void InitOther() { 
            if (this.otherType == null) {
                Type ot = this.isMany ? TypeSystem.GetElementType(this.thisMember.Type) : this.thisMember.Type; 
                this.otherType = this.thisMember.DeclaringType.Model.GetMetaType(ot); 
                System.Diagnostics.Debug.Assert(this.otherType.IsEntity);
                this.otherKey = (assocMap.OtherKey != null) 
                    ? MakeKeys(this.otherType, this.assocMap.OtherKey)
                    : this.otherType.IdentityMembers;
                this.otherKeyIsPrimaryKey = AreEqual(this.otherKey, this.otherType.IdentityMembers);
                foreach (MetaDataMember omm in this.otherType.DataMembers) { 
                    if (omm.IsAssociation && omm != this.thisMember && omm.MappedName == this.thisMember.MappedName) {
                        this.otherMember = omm; 
                        break; 
                    }
                } 
            }
        }
        #endregion
        public override MetaDataMember ThisMember { 
            get { return this.thisMember; }
        } 
        public override ReadOnlyCollection ThisKey { 
            get { return this.thisKey; }
        } 
        public override MetaDataMember OtherMember {
            get { return this.otherMember; }
        }
        public override ReadOnlyCollection OtherKey { 
            get { return this.otherKey; }
        } 
        public override MetaType OtherType { 
            get { return this.otherType; }
        } 
        public override bool IsMany {
            get { return this.isMany; }
        }
        public override bool IsForeignKey { 
            get { return this.isForeignKey; }
        } 
        public override bool IsUnique { 
            get { return this.assocMap.IsUnique; }
        } 
        public override bool IsNullable {
            get { return this.isNullable; }
        }
        public override bool ThisKeyIsPrimaryKey { 
            get { return this.thisKeyIsPrimaryKey; }
        } 
        public override bool OtherKeyIsPrimaryKey { 
            get { return this.otherKeyIsPrimaryKey; }
        } 
        public override string DeleteRule {
            get {
                return this.assocMap.DeleteRule;
            } 
        }
        public override bool DeleteOnNull { 
            get { 
                return this.assocMap.DeleteOnNull;
            } 
        }
    }

    class MappedFunction : MetaFunction { 
        MetaModel model;
        FunctionMapping map; 
        MethodInfo method; 
        ReadOnlyCollection parameters;
        MetaParameter returnParameter; 
        ReadOnlyCollection rowTypes;
        static ReadOnlyCollection _emptyParameters = new List(0).AsReadOnly();
        static ReadOnlyCollection _emptyTypes = new List(0).AsReadOnly();
 
        internal MappedFunction(MappedMetaModel model, FunctionMapping map, MethodInfo method) {
            this.model = model; 
            this.map = map; 
            this.method = method;
            this.rowTypes = _emptyTypes; 

            if (map.Types.Count == 0 && this.method.ReturnType == typeof(IMultipleResults)) {
                throw Error.NoResultTypesDeclaredForFunction(method.Name);
            } 
            else if (map.Types.Count > 1 && this.method.ReturnType != typeof(IMultipleResults)) {
                throw Error.TooManyResultTypesDeclaredForFunction(method.Name); 
            } 
            else if (map.Types.Count == 1 && this.method.ReturnType != typeof(IMultipleResults)) {
                Type elementType = TypeSystem.GetElementType(method.ReturnType); 
                this.rowTypes = new List(1) { this.GetMetaType(map.Types[0], elementType) }.AsReadOnly();
            }
            else if (map.Types.Count > 0) {
                List rowTypes = new List(); 
                foreach (TypeMapping rtm in map.Types) {
                    Type elementType = model.FindType(rtm.Name); 
                    if (elementType == null) { 
                        throw Error.CouldNotFindElementTypeInModel(rtm.Name);
                    } 
                    MetaType mt = this.GetMetaType(rtm, elementType);
                    // Only add unique meta types
                    if (!rowTypes.Contains(mt)) {
                        rowTypes.Add(mt); 
                    }
                } 
                this.rowTypes = rowTypes.AsReadOnly(); 
            }
            else if (map.FunReturn != null) { 
                this.returnParameter = new MappedReturnParameter(method.ReturnParameter, map.FunReturn);
            }

            // Parameters. 
            ParameterInfo[] pis = this.method.GetParameters();
            if (pis.Length > 0) { 
                List mps = new List(pis.Length); 
                if (this.map.Parameters.Count != pis.Length) {
                    throw Error.IncorrectNumberOfParametersMappedForMethod(this.map.MethodName); 
                }
                for (int i = 0; i < pis.Length; i++) {
                    mps.Add(new MappedParameter(pis[i], this.map.Parameters[i]));
                } 
                this.parameters = mps.AsReadOnly();
            } 
            else { 
                this.parameters = _emptyParameters;
            } 
        }
        /// 
        /// For the specified type, if it is a mapped type, use the Table
        /// metatype to get the correct inheritance metatype, 
        /// otherwise create a new meta type.
        private MetaType GetMetaType(TypeMapping tm, Type elementType) { 
            MetaTable tbl = model.GetTable(elementType); 
            if (tbl != null) {
                return tbl.RowType.GetInheritanceType(elementType); 
            }
            return new MappedRootType((MappedMetaModel)model, null, tm, elementType);
        }
        public override ReadOnlyCollection Parameters { 
            get { return this.parameters; }
        } 
        public override string MappedName { 
            get { return this.map.Name; }
        } 
        public override MethodInfo Method {
            get { return this.method; }
        }
        public override MetaModel Model { 
            get { return this.model; }
        } 
        public override string Name { 
            get { return this.method.Name; }
        } 
        public override bool IsComposable {
            get { return this.map.IsComposable; }
        }
        public override MetaParameter ReturnParameter { 
            get { return this.returnParameter; }
        } 
        public override bool HasMultipleResults { 
            get { return this.method.ReturnType == typeof(IMultipleResults); }
        } 
        public override ReadOnlyCollection ResultRowTypes {
            get { return this.rowTypes; }
        }
    } 

    internal sealed class MappedParameter : MetaParameter { 
        private ParameterInfo parameterInfo; 
        private ParameterMapping map;
 
        public MappedParameter(ParameterInfo parameterInfo, ParameterMapping map) {
            this.parameterInfo = parameterInfo;
            this.map = map;
        } 
        public override ParameterInfo Parameter {
            get { return this.parameterInfo; } 
        } 
        public override string Name {
            get { return this.parameterInfo.Name; } 
        }
        public override string MappedName {
            get { return this.map.Name; }
        } 
        public override Type ParameterType {
            get { return this.parameterInfo.ParameterType; } 
        } 
        public override string DbType {
            get { return this.map.DbType; } 
        }
    }

    internal sealed class MappedReturnParameter : MetaParameter { 
        private ParameterInfo parameterInfo;
        private ReturnMapping map; 
 
        public MappedReturnParameter(ParameterInfo parameterInfo, ReturnMapping map) {
            this.parameterInfo = parameterInfo; 
            this.map = map;
        }
        public override ParameterInfo Parameter {
            get { return this.parameterInfo; } 
        }
        public override string Name { 
            get { return null; } 
        }
        public override string MappedName { 
            get { return null; }
        }
        public override Type ParameterType {
            get { return this.parameterInfo.ParameterType; } 
        }
        public override string DbType { 
            get { return this.map.DbType; } 
        }
    } 

    internal abstract class MetaAssociationImpl : MetaAssociation {

        private static char[] keySeparators = new char[] { ',' }; 
        /// 
        /// Given a MetaType and a set of key fields, return the set of MetaDataMembers 
        /// corresponding to the key. 
        /// 
        protected static ReadOnlyCollection MakeKeys(MetaType mtype, string keyFields) { 
            string[] names = keyFields.Split(keySeparators);
            MetaDataMember[] members = new MetaDataMember[names.Length];
            for (int i = 0; i < names.Length; i++) {
                names[i] = names[i].Trim(); 
                MemberInfo[] rmis = mtype.Type.GetMember(names[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
                if (rmis == null || rmis.Length != 1) { 
                    throw Error.BadKeyMember(names[i], keyFields, mtype.Name); 
                }
                members[i] = mtype.GetDataMember(rmis[0]); 
                if (members[i] == null) {
                    throw Error.BadKeyMember(names[i], keyFields, mtype.Name);
                }
            } 
            return new List(members).AsReadOnly();
        } 
 
        /// 
        /// Compare two sets of keys for equality. 
        /// 
        protected static bool AreEqual(IEnumerable key1, IEnumerable key2) {
            using (IEnumerator e1 = key1.GetEnumerator()) {
                using (IEnumerator e2 = key2.GetEnumerator()) { 
                    bool m1, m2;
                    for (m1 = e1.MoveNext(), m2 = e2.MoveNext(); m1 && m2; m1 = e1.MoveNext(), m2 = e2.MoveNext()) { 
                        if (e1.Current != e2.Current) 
                            return false;
                    } 
                    if (m1 != m2)
                        return false;
                }
            } 
            return true;
        } 
 
        public override string ToString() {
            return string.Format(Globalization.CultureInfo.InvariantCulture, "{0} ->{1} {2}", ThisMember.DeclaringType.Name, IsMany ? "*" : "", OtherType.Name); 
        }
    }

    internal sealed class UnmappedType : MetaType { 
        MetaModel model;
        Type type; 
        Dictionary dataMemberMap; 
        ReadOnlyCollection dataMembers;
        ReadOnlyCollection inheritanceTypes; 
        object locktarget = new object(); // Hold locks on private object rather than public MetaType.

        private static ReadOnlyCollection _emptyTypes = new List().AsReadOnly();
        private static ReadOnlyCollection _emptyDataMembers = new List().AsReadOnly(); 
        private static ReadOnlyCollection _emptyAssociations = new List().AsReadOnly();
 
        internal UnmappedType(MetaModel model, Type type) { 
            this.model = model;
            this.type = type; 
        }

        public override MetaModel Model {
            get { return this.model; } 
        }
        public override MetaTable Table { 
            get { return null; } 
        }
        public override Type Type { 
            get { return this.type; }
        }
        public override string Name {
            get { return this.type.Name; } 
        }
        public override bool IsEntity { 
            get { return false; } 
        }
        public override bool CanInstantiate { 
            get { return !this.type.IsAbstract; }
        }
        public override MetaDataMember DBGeneratedIdentityMember {
            get { return null; } 
        }
        public override MetaDataMember VersionMember { 
            get { return null; } 
        }
        public override MetaDataMember Discriminator { 
            get { return null; }
        }
        public override bool HasUpdateCheck {
            get { return false; } 
        }
        public override ReadOnlyCollection InheritanceTypes { 
            get { 
                if (this.inheritanceTypes == null) {
                    lock (this.locktarget) { 
                        if (this.inheritanceTypes == null) {
                            this.inheritanceTypes = new MetaType[] { this }.ToList().AsReadOnly();
                        }
                    } 
                }
                return this.inheritanceTypes; 
            } 
        }
        public override MetaType GetInheritanceType(Type inheritanceType) { 
            if (inheritanceType == this.type)
                return this;
            return null;
        } 
        public override ReadOnlyCollection DerivedTypes {
            get { return _emptyTypes; } 
        } 
        public override MetaType GetTypeForInheritanceCode(object key) {
            return null; 
        }
        public override bool HasInheritance {
            get { return false; }
        } 
        public override bool HasInheritanceCode {
            get { return false; } 
        } 
        public override object InheritanceCode {
            get { return null; } 
        }
        public override MetaType InheritanceRoot {
            get { return this; }
        } 
        public override MetaType InheritanceBase {
            get { return null; } 
        } 
        public override MetaType InheritanceDefault {
            get { return null; } 
        }
        public override bool IsInheritanceDefault {
            get { return false; }
        } 
        public override ReadOnlyCollection DataMembers {
            get { 
                this.InitDataMembers(); 
                return this.dataMembers;
            } 
        }
        public override ReadOnlyCollection PersistentDataMembers {
            get { return _emptyDataMembers; }
        } 
        public override ReadOnlyCollection IdentityMembers {
            get { 
                this.InitDataMembers(); 
                return this.dataMembers;
            } 
        }
        public override ReadOnlyCollection Associations {
            get { return _emptyAssociations; }
        } 
        public override MetaDataMember GetDataMember(MemberInfo mi) {
            if (mi == null) 
                throw Error.ArgumentNull("mi"); 
            this.InitDataMembers();
            if (this.dataMemberMap == null) { 
                lock (this.locktarget) {
                    if (this.dataMemberMap == null) {
                        Dictionary map = new Dictionary();
                        foreach (MetaDataMember mm in this.dataMembers) { 
                            map.Add(InheritanceRules.DistinguishedMemberName(mm.Member), mm);
                        } 
                        this.dataMemberMap = map; 
                    }
                } 
            }
            object dn = InheritanceRules.DistinguishedMemberName(mi);
            MetaDataMember mdm;
            this.dataMemberMap.TryGetValue(dn, out mdm); 
            return mdm;
        } 
 
        private void InitDataMembers() {
            if (this.dataMembers == null) { 
                lock (this.locktarget) {
                    if (this.dataMembers == null) {
                        List dMembers = new List();
                        int ordinal = 0; 
                        BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
                        foreach (FieldInfo fi in this.type.GetFields(flags)) { 
                            MetaDataMember mm = new UnmappedDataMember(this, fi, ordinal); 
                            dMembers.Add(mm);
                            ordinal++; 
                        }
                        foreach (PropertyInfo pi in this.type.GetProperties(flags)) {
                            MetaDataMember mm = new UnmappedDataMember(this, pi, ordinal);
                            dMembers.Add(mm); 
                            ordinal++;
                        } 
                        this.dataMembers = dMembers.AsReadOnly(); 
                    }
                } 
            }
        }

        public override string ToString() { 
            return this.Name;
        } 
 
        public override MethodInfo OnLoadedMethod {
            get { return null; } 
        }

        public override MethodInfo OnValidateMethod {
            get { return null; } 
        }
        public override bool HasAnyValidateMethod { 
            get { 
                return false;
            } 
        }
        public override bool HasAnyLoadMethod {
            get {
                return false; 
            }
        } 
    } 

    internal sealed class UnmappedDataMember : MetaDataMember { 
        MetaType declaringType;
        MemberInfo member;
        int ordinal;
        Type type; 
        MetaAccessor accPublic;
        object lockTarget = new object(); 
 
        internal UnmappedDataMember(MetaType declaringType, MemberInfo mi, int ordinal) {
            this.declaringType = declaringType; 
            this.member = mi;
            this.ordinal = ordinal;
            this.type = TypeSystem.GetMemberType(mi);
        } 
        private void InitAccessors() {
            if (this.accPublic == null) { 
                lock (this.lockTarget) { 
                    if (this.accPublic == null) {
                        this.accPublic = MakeMemberAccessor(this.member.ReflectedType, this.member); 
                    }
                }
            }
        } 
        public override MetaType DeclaringType {
            get { return this.declaringType; } 
        } 
        public override bool IsDeclaredBy(MetaType metaType) {
            if (metaType == null) { 
                throw Error.ArgumentNull("metaType");
            }
            return metaType.Type == this.member.DeclaringType;
        } 
        public override MemberInfo Member {
            get { return this.member; } 
        } 
        public override MemberInfo StorageMember {
            get { return this.member; } 
        }
        public override string Name {
            get { return this.member.Name; }
        } 
        public override int Ordinal {
            get { return this.ordinal; } 
        } 
        public override Type Type {
            get { return this.type; } 
        }
        public override MetaAccessor MemberAccessor {
            get {
                this.InitAccessors(); 
                return this.accPublic;
            } 
        } 
        public override MetaAccessor StorageAccessor {
            get { 
                this.InitAccessors();
                return this.accPublic;
            }
        } 
        public override MetaAccessor DeferredValueAccessor {
            get { return null; } 
        } 
        public override MetaAccessor DeferredSourceAccessor {
            get { return null; } 
        }
        public override bool IsDeferred {
            get { return false; }
        } 
        public override bool IsPersistent {
            get { return false; } 
        } 
        public override bool IsAssociation {
            get { return false; } 
        }
        public override bool IsPrimaryKey {
            get { return false; }
        } 
        public override bool IsDbGenerated {
            get { return false; } 
        } 
        public override bool IsVersion {
            get { return false; } 
        }
        public override bool IsDiscriminator {
            get { return false; }
        } 
        public override bool CanBeNull {
            get { return !this.type.IsValueType || TypeSystem.IsNullableType(this.type); } 
        } 
        public override string DbType {
            get { return null; } 
        }
        public override string Expression {
            get { return null; }
        } 
        public override string MappedName {
            get { return this.member.Name; } 
        } 
        public override UpdateCheck UpdateCheck {
            get { return UpdateCheck.Never; } 
        }
        public override AutoSync AutoSync {
            get { return AutoSync.Never; }
        } 
        public override MetaAssociation Association {
            get { return null; } 
        } 
        public override MethodInfo LoadMethod {
            get { return null; } 
        }
        private static MetaAccessor MakeMemberAccessor(Type accessorType, MemberInfo mi) {
            FieldInfo fi = mi as FieldInfo;
            MetaAccessor acc = null; 
            if (fi != null) {
                acc = FieldAccessor.Create(accessorType, fi); 
            } 
            else {
                PropertyInfo pi = (PropertyInfo)mi; 
                acc = PropertyAccessor.Create(accessorType, pi, null);
            }
            return acc;
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System; 
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq.Expressions; 
using System.Reflection;
using System.Text; 
using System.Linq; 
using System.Data.Linq.Provider;
using System.Data.Linq.Mapping; 
using System.Data.Linq.SqlClient;
using System.Threading;
using LinqToSqlShared.Mapping;
 
namespace System.Data.Linq.Mapping {
 
    internal class MappedMetaModel : MetaModel { 
        ReaderWriterLock @lock = new ReaderWriterLock();
        MappingSource mappingSource; 
        Type contextType;
        Type providerType;
        DatabaseMapping mapping;
        HashSet modules; 
        Dictionary types;
        Dictionary metaTypes; 
        Dictionary metaTables; 
        Dictionary metaFunctions;
        bool fullyLoaded; 

        internal MappedMetaModel(MappingSource mappingSource, Type contextType, DatabaseMapping mapping) {
            this.mappingSource = mappingSource;
            this.contextType = contextType; 
            this.mapping = mapping;
            this.modules = new HashSet(); 
            this.modules.Add(this.contextType.Module); 
            this.metaTypes = new Dictionary();
            this.metaTables = new Dictionary(); 
            this.types = new Dictionary();
            // Provider type
            if (this.providerType == null && !String.IsNullOrEmpty(this.mapping.Provider)) {
                this.providerType = this.FindType(this.mapping.Provider, typeof(SqlProvider).Namespace); 
                if (this.providerType == null) {
                    throw Error.ProviderTypeNotFound(this.mapping.Provider); 
                } 
            }
            else if (this.providerType == null) { 
                this.providerType = typeof(SqlProvider);
            }
            this.Init();
        } 
        #region Initialization
        private void Init() { 
            if (!fullyLoaded) { 
                // The fullyLoaded state is required so that tools like
                // CreateDatabase can get a full view of all tables. 
                @lock.AcquireWriterLock(Timeout.Infinite);
                try {
                    if (!fullyLoaded) {
                        // Initialize static tables and functions. 
                        this.InitStaticTables();
                        this.InitFunctions(); 
                        fullyLoaded = true; 
                    }
                } 
                finally {
                    @lock.ReleaseWriterLock();
                }
            } 
        }
 
        private void InitStaticTables() { 
            this.InitStaticTableTypes();
            foreach (TableMapping tableMapping in this.mapping.Tables) { 
                Type rowType = this.FindType(tableMapping.RowType.Name);
                if (rowType == null) {
                    throw Error.CouldNotFindTypeFromMapping(tableMapping.RowType.Name);
                } 
                Type rootType = this.GetRootType(rowType, tableMapping.RowType);
                MetaTable table = new MappedTable(this, tableMapping, rootType); 
                foreach (MetaType mt in table.RowType.InheritanceTypes) { 
                    this.metaTypes.Add(mt.Type, mt);
                    this.metaTables.Add(mt.Type, table); 
                }
            }
        }
 
        private void InitStaticTableTypes() {
            for (Type type = this.contextType; type != typeof(DataContext); type = type.BaseType) { 
                FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); 
                foreach (FieldInfo fi in fields) {
                    Type ft = fi.FieldType; 
                    if (ft.IsGenericType && ft.GetGenericTypeDefinition() == typeof(Table<>)) {
                        Type rowType = ft.GetGenericArguments()[0];
                        if (!this.types.ContainsKey(rowType.Name)) {
                            this.types.Add(rowType.FullName, rowType); 
                            if (!this.types.ContainsKey(rowType.Name)) {
                                this.types.Add(rowType.Name, rowType); 
                            } 
                            this.modules.Add(rowType.Module);
                        } 
                    }
                }
                PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
                foreach (PropertyInfo pi in props) { 
                    Type pt = pi.PropertyType;
                    if (pt.IsGenericType && pt.GetGenericTypeDefinition() == typeof(Table<>)) { 
                        Type rowType = pt.GetGenericArguments()[0]; 
                        if (!this.types.ContainsKey(rowType.Name)) {
                            this.types.Add(rowType.FullName, rowType); 
                            if (!this.types.ContainsKey(rowType.Name)) {
                                this.types.Add(rowType.Name, rowType);
                            }
                            this.modules.Add(rowType.Module); 
                        }
                    } 
                } 
            }
        } 

        private void InitFunctions() {
            this.metaFunctions = new Dictionary();
            if (this.contextType != typeof(DataContext)) { 
                foreach (FunctionMapping fmap in this.mapping.Functions) {
                    MethodInfo method = this.GetMethod(fmap.MethodName); 
                    if (method == null) { 
                        throw Error.MethodCannotBeFound(fmap.MethodName);
                    } 
                    MappedFunction func = new MappedFunction(this, fmap, method);
                    this.metaFunctions.Add(new MetaPosition(method), func);

                    // pre-set all known function result types into metaType map 
                    foreach (MetaType rt in func.ResultRowTypes) {
                        foreach (MetaType it in rt.InheritanceTypes) { 
                            if (!this.metaTypes.ContainsKey(it.Type)) { 
                                this.metaTypes.Add(it.Type, it);
                            } 
                        }
                    }
                }
            } 
        }
        #endregion 
 
        public override MappingSource MappingSource {
            get { return this.mappingSource; } 
        }

        public override Type ContextType {
            get { return this.contextType; } 
        }
 
        public override string DatabaseName { 
            get { return this.mapping.DatabaseName; }
        } 

        public override Type ProviderType {
            get { return this.providerType; }
        } 

        public override IEnumerable GetTables() { 
            return this.metaTables.Values.Where(x => x != null).Distinct(); 
        }
 
        public override MetaTable GetTable(Type rowType) {
            if (rowType == null) {
                throw Error.ArgumentNull("rowType");
            } 
            MetaTable table = null;
            this.metaTables.TryGetValue(rowType, out table); 
            return table; 
        }
 
        public override MetaType GetMetaType(Type type) {
            if (type == null) {
                throw Error.ArgumentNull("type");
            } 
            MetaType mtype = null;
            @lock.AcquireReaderLock(Timeout.Infinite); 
            try { 
                if (this.metaTypes.TryGetValue(type, out mtype)) {
                    return mtype; 
                }
            }
            finally {
                @lock.ReleaseReaderLock(); 
            }
            @lock.AcquireWriterLock(Timeout.Infinite); 
            try { 
                if (!this.metaTypes.TryGetValue(type, out mtype)) {
                    // not known, so must be unmapped type 
                    mtype = new UnmappedType(this, type);
                    this.metaTypes.Add(type, mtype);
                }
            } 
            finally {
                @lock.ReleaseWriterLock(); 
            } 
            return mtype;
        } 

        public override MetaFunction GetFunction(MethodInfo method) {
            if (method == null) {
                throw new ArgumentNullException("method"); 
            }
            MetaFunction func = null; 
            this.metaFunctions.TryGetValue(new MetaPosition(method), out func); 
            return func;
        } 

        public override IEnumerable GetFunctions() {
            return this.metaFunctions.Values;
        } 

        private Type GetRootType(Type type, TypeMapping rootMapping) { 
            if (string.Compare(rootMapping.Name, type.Name, StringComparison.Ordinal) == 0 
                || string.Compare(rootMapping.Name, type.FullName, StringComparison.Ordinal) == 0
                || string.Compare(rootMapping.Name, type.AssemblyQualifiedName, StringComparison.Ordinal) == 0) 
                return type;
            if (type.BaseType != typeof(object)) {
                return this.GetRootType(type.BaseType, rootMapping);
            } 
            throw Error.UnableToResolveRootForType(type);
        } 
 
        private MethodInfo GetMethod(string name) {
            string typeName, methodName; 
            this.GetTypeAndMethod(name, out typeName, out methodName);
            Type type = this.FindType(typeName);
            if (type != null) {
                return type.GetMethod(methodName, BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic); 
            }
            return null; 
        } 

        private void GetTypeAndMethod(string name, out string typeName, out string methodName) { 
            int dotIndex = name.LastIndexOf(".", StringComparison.CurrentCulture);
            if (dotIndex > 0) {
                typeName = name.Substring(0, dotIndex);
                methodName = name.Substring(dotIndex + 1); 
            }
            else { 
                typeName = this.contextType.FullName; 
                methodName = name;
            } 
        }

        internal Type FindType(string name) {
            return this.FindType(name, this.contextType.Namespace); 
        }
 
        internal Type FindType(string name, string defaultNamespace) { 
            Type result = null;
            string name2 = null; 
            @lock.AcquireReaderLock(Timeout.Infinite);
            try {
                if (this.types.TryGetValue(name, out result)) {
                    return result; 
                }
                name2 = name.Contains(".") ? null : defaultNamespace + "." + name; 
                if (name2 != null && this.types.TryGetValue(name2, out result)) { 
                    return result;
                } 
            }
            finally {
                @lock.ReleaseReaderLock();
            } 
            // don't block anyone while we search for the correct type
            Type foundResult = this.SearchForType(name); 
 
            if (foundResult == null && name2 != null) {
                foundResult = this.SearchForType(name2); 
            }
            if (foundResult != null) {
                @lock.AcquireWriterLock(Timeout.Infinite);
                try { 
                    if (this.types.TryGetValue(name, out result)) {
                        return result; 
                    } 
                    this.types.Add(name, foundResult);
                    return foundResult; 
                }
                finally {
                    @lock.ReleaseWriterLock();
                } 
            }
            return null; 
        } 

        private Type SearchForType(string name) { 
            // Try search for type using case sensitive.
            Type type = SearchForType(name, false);
            if (type != null) {
                return type; 
            }
 
            // Try search for type using case in-sensitive. 
            return SearchForType(name, true);
        } 

        private Type SearchForType(string name, bool ignoreCase) {
            // first try default system lookup
            Type type = Type.GetType(name, false, ignoreCase); 
            if (type != null) {
                return type; 
            } 

            // try all known modules (modules that other statically known types were found in) 
            foreach (Module module in this.modules) {
                type = module.GetType(name, false, ignoreCase);
                if (type != null) {
                    return type; 
                }
            } 
 
            // try all loaded modules (is there a better way?)
            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) { 
                foreach (Module module in a.GetLoadedModules()) {
                    type = module.GetType(name, false, ignoreCase);
                    if (type != null) {
                        return type; 
                    }
                } 
            } 

            return null; 
        }
    }

    internal sealed class MappedTable : MetaTable { 
        MappedMetaModel model;
        TableMapping mapping; 
        MetaType rowType; 
        bool hasMethods;
        MethodInfo insertMethod; 
        MethodInfo updateMethod;
        MethodInfo deleteMethod;

        internal MappedTable(MappedMetaModel model, TableMapping mapping, Type rowType) { 
            this.model = model;
            this.mapping = mapping; 
            this.rowType = new MappedRootType(model, this, mapping.RowType, rowType); 
        }
        public override MetaModel Model { 
            get { return this.model; }
        }
        public override string TableName {
            get { return this.mapping.TableName; } 
        }
        public override MetaType RowType { 
            get { return this.rowType; } 
        }
        public override MethodInfo InsertMethod { 
            get {
                this.InitMethods();
                return this.insertMethod;
            } 
        }
        public override MethodInfo UpdateMethod { 
            get { 
                this.InitMethods();
                return this.updateMethod; 
            }
        }
        public override MethodInfo DeleteMethod {
            get { 
                this.InitMethods();
                return this.deleteMethod; 
            } 
        }
        private void InitMethods() { 
            if (!this.hasMethods) {
                this.insertMethod = MethodFinder.FindMethod(
                    this.model.ContextType,
                    "Insert" + rowType.Name, 
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    new Type[] { rowType.Type } 
                    ); 
                this.updateMethod = MethodFinder.FindMethod(
                    this.model.ContextType, 
                    "Update" + rowType.Name,
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    new Type[] { rowType.Type }
                    ); 
                this.deleteMethod = MethodFinder.FindMethod(
                    this.model.ContextType, 
                    "Delete" + rowType.Name, 
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    new Type[] { rowType.Type } 
                    );
                this.hasMethods = true;
            }
        } 
    }
 
    internal sealed class MappedRootType : MappedType { 
        Dictionary derivedTypes;
        Dictionary inheritanceCodes; 
        ReadOnlyCollection inheritanceTypes;
        MetaType inheritanceDefault;
        bool hasInheritance;
 
        public MappedRootType(MappedMetaModel model, MappedTable table, TypeMapping typeMapping, Type type)
            : base(model, table, typeMapping, type, null) { 
            if (typeMapping == null) 
                throw Error.ArgumentNull("typeMapping");
 
            if (typeMapping.InheritanceCode != null || typeMapping.DerivedTypes.Count > 0) {
                if (this.Discriminator == null) {
                    throw Error.NoDiscriminatorFound(type.Name);
                } 
                this.hasInheritance = true;
                if (!MappingSystem.IsSupportedDiscriminatorType(this.Discriminator.Type)) { 
                    throw Error.DiscriminatorClrTypeNotSupported(this.Discriminator.DeclaringType.Name, this.Discriminator.Name, this.Discriminator.Type); 
                }
                this.derivedTypes = new Dictionary(); 
                this.inheritanceCodes = new Dictionary();
                this.InitInheritedType(typeMapping, this);
            }
 
            if (this.inheritanceDefault == null && (this.inheritanceCode != null || this.inheritanceCodes != null && this.inheritanceCodes.Count > 0))
                throw Error.InheritanceHierarchyDoesNotDefineDefault(type); 
 
            if (this.derivedTypes != null) {
                this.inheritanceTypes = this.derivedTypes.Values.ToList().AsReadOnly(); 
            }
            else {
                this.inheritanceTypes = new MetaType[] { this }.ToList().AsReadOnly();
            } 

            this.Validate(); 
        } 

        private void Validate() { 
            Dictionary memberToColumn = new Dictionary();
            foreach (MetaType type in this.InheritanceTypes) {
                // NB: Table node in XML can have only one Type node -- enforced by XSD
 
                foreach (MetaDataMember mem in type.PersistentDataMembers) {
                    if (mem.IsDeclaredBy(type)) { 
                        if (mem.IsDiscriminator && !this.HasInheritance) { 
                            throw Error.NonInheritanceClassHasDiscriminator(type);
                        } 
                        if (!mem.IsAssociation) {
                            // validate that no database column is mapped twice
                            if (!string.IsNullOrEmpty(mem.MappedName)) {
                                string column; 
                                object dn = InheritanceRules.DistinguishedMemberName(mem.Member);
                                if (memberToColumn.TryGetValue(dn, out column)) { 
                                    if (column != mem.MappedName) { 
                                        throw Error.MemberMappedMoreThanOnce(mem.Member.Name);
                                    } 
                                }
                                else {
                                    memberToColumn.Add(dn, mem.MappedName);
                                } 
                            }
                        } 
                    } 
                }
            } 
        }

        private MetaType InitDerivedTypes(TypeMapping typeMap) {
            Type type = ((MappedMetaModel)Model).FindType(typeMap.Name); 
            if (type == null)
                throw Error.CouldNotFindRuntimeTypeForMapping(typeMap.Name); 
            MappedType rowType = new MappedType(this.Model, this.Table, typeMap, type, this); 
            return this.InitInheritedType(typeMap, rowType);
        } 

        private MetaType InitInheritedType(TypeMapping typeMap, MappedType type) {
            this.derivedTypes.Add(type.Type, type);
 
            if (typeMap.InheritanceCode != null) { // Mapping with no inheritance code: For example, an unmapped intermediate class in a hierarchy.
                if (this.Discriminator == null) 
                    throw Error.NoDiscriminatorFound(type.Name); 

                if (type.Type.IsAbstract) 
                    throw Error.AbstractClassAssignInheritanceDiscriminator(type.Type);

                object keyValue = DBConvert.ChangeType(typeMap.InheritanceCode, this.Discriminator.Type);
                foreach (object d in inheritanceCodes.Keys) { 
                    // if the keys are equal, or if they are both strings containing only spaces
                    // they are considered equal 
                    if ((keyValue.GetType() == typeof(string) && ((string)keyValue).Trim().Length == 0 && 
                        d.GetType() == typeof(string) && ((string)d).Trim().Length == 0) ||
                        object.Equals(d, keyValue)) { 
                        throw Error.InheritanceCodeUsedForMultipleTypes(keyValue);
                    }
                }
                if (type.inheritanceCode != null) 
                    throw Error.InheritanceTypeHasMultipleDiscriminators(type);
                type.inheritanceCode = keyValue; 
                this.inheritanceCodes.Add(keyValue, type); 
                if (typeMap.IsInheritanceDefault) {
                    if (this.inheritanceDefault != null) 
                        throw Error.InheritanceTypeHasMultipleDefaults(type);
                    this.inheritanceDefault = type;
                }
            } 

            // init sub-inherited types 
            foreach (TypeMapping tm in typeMap.DerivedTypes) { 
                this.InitDerivedTypes(tm);
            } 

            return type;
        }
 
        public override bool HasInheritance {
            get { return this.hasInheritance; } 
        } 

        public override bool HasInheritanceCode { 
            get { return this.InheritanceCode != null; }
        }

        public override ReadOnlyCollection InheritanceTypes { 
            get { return this.inheritanceTypes; }
        } 
 
        public override MetaType GetInheritanceType(Type type) {
            if (type == this.Type) 
                return this;
            MetaType metaType = null;
            if (this.derivedTypes != null) {
                this.derivedTypes.TryGetValue(type, out metaType); 
            }
            return metaType; 
        } 

        public override MetaType InheritanceDefault { 
            get { return this.inheritanceDefault; }
        }
    }
 
    internal class MappedType : MetaType {
        MetaModel model; 
        MetaTable table; 
        Type type;
        TypeMapping typeMapping; 
        Dictionary dataMemberMap;
        ReadOnlyCollection dataMembers;
        ReadOnlyCollection persistentDataMembers;
        ReadOnlyCollection identities; 
        MetaDataMember dbGeneratedIdentity;
        MetaDataMember version; 
        MetaDataMember discriminator; 
        MetaType inheritanceRoot;
        bool inheritanceBaseSet; 
        MetaType inheritanceBase;
        internal object inheritanceCode;
        ReadOnlyCollection derivedTypes;
        ReadOnlyCollection associations; 
        bool hasMethods;
        bool hasAnyLoadMethod; 
        bool hasAnyValidateMethod; 
        MethodInfo onLoadedMethod;
        MethodInfo onValidateMethod; 

        object locktarget = new object(); // Hold locks on private object rather than public MetaType.

        internal MappedType(MetaModel model, MetaTable table, TypeMapping typeMapping, Type type, MetaType inheritanceRoot) { 
            this.model = model;
            this.table = table; 
            this.typeMapping = typeMapping; 
            this.type = type;
            this.inheritanceRoot = inheritanceRoot != null ? inheritanceRoot : this; 
            this.InitDataMembers();

            this.identities = this.dataMembers.Where(m => m.IsPrimaryKey).ToList().AsReadOnly();
            this.persistentDataMembers = this.dataMembers.Where(m => m.IsPersistent).ToList().AsReadOnly(); 
        }
        #region Initialization 
        private void ValidatePrimaryKeyMember(MetaDataMember mm) { 
            //if the type is a sub-type, no member in the type can be primary key
            if (mm.IsPrimaryKey && this.inheritanceRoot != this && mm.Member.DeclaringType == this.type) { 
                throw (Error.PrimaryKeyInSubTypeNotSupported(this.type.Name, mm.Name));
            }
        }
 
        private void InitMethods() {
            if (!this.hasMethods) { 
                this.onLoadedMethod = MethodFinder.FindMethod( 
                    this.Type,
                    "OnLoaded", 
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    Type.EmptyTypes,
                    false
                    ); 
                this.onValidateMethod = MethodFinder.FindMethod(
                    this.Type, 
                    "OnValidate", 
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    new[] { typeof(ChangeAction) }, 
                    false
                    );

                this.hasAnyLoadMethod = (this.onLoadedMethod != null) || (this.InheritanceBase != null && this.InheritanceBase.HasAnyLoadMethod); 
                this.hasAnyValidateMethod = (this.onValidateMethod != null) || (this.InheritanceBase != null && this.InheritanceBase.HasAnyValidateMethod);
 
                this.hasMethods = true; 
            }
        } 

        private void InitDataMembers() {
            if (this.dataMembers == null) {
                Dictionary map = new Dictionary(); 
                List dMembers = new List();
                int ordinal = 0; 
                BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; 

                // Map of valid mapped names. 
                Dictionary names = new Dictionary();
                Type currentType = this.type;
                for (TypeMapping tm = this.typeMapping; tm != null; tm = tm.BaseType) {
                    foreach (MemberMapping mmap in tm.Members) { 
                        names[mmap.MemberName + ":" + currentType.Name] = mmap;
                    } 
                    currentType = currentType.BaseType; 
                }
 
                HashSet namesSeen = new HashSet(); // Keep track of which names from the mapping file have been seen.
                FieldInfo[] fis = TypeSystem.GetAllFields(this.type, flags).ToArray();
                if (fis != null) {
                    foreach (FieldInfo fi in fis) { 
                        MemberMapping mmap;
                        string name = fi.Name + ":" + fi.DeclaringType.Name; 
                        if (names.TryGetValue(name, out mmap)) { 
                            namesSeen.Add(name);
                            object dn = InheritanceRules.DistinguishedMemberName(fi); 
                            MetaDataMember mm;
                            if (!map.TryGetValue(dn, out mm)) {
                                mm = new MappedDataMember(this, fi, mmap, ordinal);
                                map.Add(InheritanceRules.DistinguishedMemberName(mm.Member), mm); 
                                dMembers.Add(mm);
                                this.InitSpecialMember(mm); 
                            } 
                            ValidatePrimaryKeyMember(mm);
                            ordinal++; 
                        }
                    }
                }
 
                PropertyInfo[] pis = TypeSystem.GetAllProperties(this.type, flags).ToArray();
                if (pis != null) { 
                    foreach (PropertyInfo pi in pis) { 
                        MemberMapping mmap;
                        string name = pi.Name + ":" + pi.DeclaringType.Name; 
                        if (names.TryGetValue(name, out mmap)) {
                            namesSeen.Add(name);
                            MetaDataMember mm;
                            object dn = InheritanceRules.DistinguishedMemberName(pi); 
                            if (!map.TryGetValue(dn, out mm)) {
                                mm = new MappedDataMember(this, pi, mmap, ordinal); 
                                map.Add(InheritanceRules.DistinguishedMemberName(mm.Member), mm); 
                                dMembers.Add(mm);
                                this.InitSpecialMember(mm); 
                            }
                            ValidatePrimaryKeyMember(mm);
                            ordinal++;
                        } 
                    }
                } 
 
                this.dataMembers = dMembers.AsReadOnly();
                this.dataMemberMap = map; 

                // Finally, make sure that all types in the mapping file were consumed.
                foreach(string name in namesSeen) {
                    names.Remove(name); 
                }
                foreach(var orphan in names) { 
                    Type aboveRoot = inheritanceRoot.Type.BaseType; 
                    while (aboveRoot!=null) {
                        foreach(MemberInfo mi in aboveRoot.GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { 
                            if(String.Compare(mi.Name, orphan.Value.MemberName, StringComparison.Ordinal)==0) {
                                throw Error.MappedMemberHadNoCorrespondingMemberInType(orphan.Value.MemberName, type.Name);
                            }
                        } 
                        aboveRoot = aboveRoot.BaseType;
                    } 
                } 
            }
        } 
        private void InitSpecialMember(MetaDataMember mm) {
            // Can only have one auto gen member that is also an identity member,
            // except if that member is a computed column (since they are implicitly auto gen)
            if (mm.IsDbGenerated && mm.IsPrimaryKey && string.IsNullOrEmpty(mm.Expression)) { 
                if (this.dbGeneratedIdentity != null) {
                    throw Error.TwoMembersMarkedAsPrimaryKeyAndDBGenerated(mm.Member, this.dbGeneratedIdentity.Member); 
                } 
                this.dbGeneratedIdentity = mm;
            } 
            if (mm.IsPrimaryKey && !MappingSystem.IsSupportedIdentityType(mm.Type))
            {
                throw Error.IdentityClrTypeNotSupported(mm.DeclaringType, mm.Name, mm.Type);
            } 
            if (mm.IsVersion) {
                if (this.version != null) { 
                    throw Error.TwoMembersMarkedAsRowVersion(mm.Member, this.version.Member); 
                }
                this.version = mm; 
            }
            if (mm.IsDiscriminator) {
                if (this.discriminator != null) {
                    if (!InheritanceRules.AreSameMember(this.discriminator.Member, mm.Member)) { 
                        throw Error.TwoMembersMarkedAsInheritanceDiscriminator(mm.Member, this.discriminator.Member);
                    } 
                } 
                else {
                    this.discriminator = mm; 
                }
            }
        }
        #endregion 
        public override MetaModel Model {
            get { return this.model; } 
        } 
        public override MetaTable Table {
            get { return this.table; } 
        }
        public override Type Type {
            get { return this.type; }
        } 
        public override string Name {
            get { return this.type.Name; } 
        } 
        public override bool IsEntity {
            get { 
                if (this.table != null) {
                    return table.RowType.IdentityMembers.Count > 0;
                }
                return false; 
            }
 
        } 
        public override bool CanInstantiate {
            get { return !this.type.IsAbstract && (this == this.InheritanceRoot || this.HasInheritanceCode); } 
        }
        public override MetaDataMember DBGeneratedIdentityMember {
            get { return this.dbGeneratedIdentity; }
        } 
        public override MetaDataMember VersionMember {
            get { return this.version; } 
        } 
        public override MetaDataMember Discriminator {
            get { return this.discriminator; } 
        }
        public override bool HasUpdateCheck {
            get {
                foreach (MetaDataMember member in this.PersistentDataMembers) { 
                    if (member.UpdateCheck != UpdateCheck.Never) {
                        return true; 
                    } 
                }
                return false; 
            }
        }
        public override bool HasInheritance {
            get { return this.inheritanceRoot.HasInheritance; } 
        }
        public override object InheritanceCode { 
            get { return this.inheritanceCode; } 
        }
        public override bool HasInheritanceCode { 
            get { return this.InheritanceCode != null; }
        }
        public override bool IsInheritanceDefault {
            get { return this.InheritanceDefault == this; } 
        }
        public override MetaType InheritanceDefault { 
            get { 
                if (this.inheritanceRoot == this)
                    throw Error.CannotGetInheritanceDefaultFromNonInheritanceClass(); 
                return this.InheritanceRoot.InheritanceDefault;
            }
        }
        public override MetaType InheritanceRoot { 
            get { return this.inheritanceRoot; }
        } 
        public override MetaType InheritanceBase { 
            get {
                // LOCKING: Cannot initialize at construction 
                if (!this.inheritanceBaseSet && this.inheritanceBase == null) {
                    lock (this.locktarget) {
                        if (this.inheritanceBase == null) {
                            this.inheritanceBase = InheritanceBaseFinder.FindBase(this); 
                            this.inheritanceBaseSet = true;
                        } 
                    } 
                }
                return this.inheritanceBase; 
            }
        }
        public override ReadOnlyCollection InheritanceTypes {
            get { return this.inheritanceRoot.InheritanceTypes; } 
        }
        public override ReadOnlyCollection DerivedTypes { 
            get { 
                // LOCKING: Cannot initialize at construction because derived types
                // won't exist yet. 
                if (this.derivedTypes == null) {
                    lock (this.locktarget) {
                        if (this.derivedTypes == null) {
                            List dTypes = new List(); 
                            foreach (MetaType mt in this.InheritanceTypes) {
                                if (mt.Type.BaseType == this.type) 
                                    dTypes.Add(mt); 
                            }
                            this.derivedTypes = dTypes.AsReadOnly(); 
                        }
                    }
                }
                return this.derivedTypes; 
            }
        } 
        public override MetaType GetInheritanceType(Type inheritanceType) { 
            foreach (MetaType mt in this.InheritanceTypes)
                if (mt.Type == inheritanceType) 
                    return mt;
            return null;
        }
        public override MetaType GetTypeForInheritanceCode(object key) { 
            if (this.InheritanceRoot.Discriminator.Type == typeof(string)) {
                string skey = (string)key; 
                foreach (MetaType mt in this.InheritanceRoot.InheritanceTypes) { 
                    if (string.Compare((string)mt.InheritanceCode, skey, StringComparison.OrdinalIgnoreCase) == 0)
                        return mt; 
                }
            }
            else {
                foreach (MetaType mt in this.InheritanceRoot.InheritanceTypes) { 
                    if (object.Equals(mt.InheritanceCode, key))
                        return mt; 
                } 
            }
            return null; 
        }
        public override ReadOnlyCollection DataMembers {
            get { return this.dataMembers; }
        } 
        public override ReadOnlyCollection PersistentDataMembers {
            get { return this.persistentDataMembers; } 
        } 
        public override ReadOnlyCollection IdentityMembers {
            get { return this.identities; } 
        }
        public override ReadOnlyCollection Associations {
            get {
                // LOCKING: Associations are late-expanded so that cycles are broken. 
                if (this.associations == null) {
                    lock (this.locktarget) { 
                        if (this.associations == null) { 
                            this.associations = this.dataMembers.Where(m => m.IsAssociation).Select(m => m.Association).ToList().AsReadOnly();
                        } 
                    }
                }
                return this.associations;
            } 
        }
        public override MetaDataMember GetDataMember(MemberInfo mi) { 
            if (mi == null) 
                throw Error.ArgumentNull("mi");
            MetaDataMember mm; 
            if (this.dataMemberMap.TryGetValue(InheritanceRules.DistinguishedMemberName(mi), out mm)) {
                return mm;
            } else {
                if (mi.DeclaringType.IsInterface) { 
                    throw Error.MappingOfInterfacesMemberIsNotSupported(mi.DeclaringType.Name, mi.Name);
                } else { //the member is not mapped in the base class 
                    throw Error.UnmappedClassMember(mi.DeclaringType.Name, mi.Name); 
                }
            } 
        }

        public override MethodInfo OnLoadedMethod {
            get { 
                this.InitMethods();
                return this.onLoadedMethod; 
            } 
        }
 
        public override MethodInfo OnValidateMethod {
            get {
                this.InitMethods();
                return this.onValidateMethod; 
            }
        } 
        public override bool HasAnyValidateMethod { 
            get {
                this.InitMethods(); 
                return this.hasAnyValidateMethod;
            }
        }
        public override bool HasAnyLoadMethod { 
            get {
                this.InitMethods(); 
                return this.hasAnyLoadMethod; 
            }
        } 

        public override string ToString() {
            return this.Name;
        } 
    }
 
    internal sealed class MappedDataMember : MetaDataMember { 
        MetaType declaringType;
        MemberInfo member; 
        MemberInfo storageMember;
        int ordinal;
        Type type;
        bool hasAccessors; 
        MetaAccessor accPublic;
        MetaAccessor accPrivate; 
        MetaAccessor accDefValue; 
        MetaAccessor accDefSource;
        MemberMapping memberMap; 
        MappedAssociation assoc;
        bool isNullableType;
        bool isDeferred;
        bool isPrimaryKey; 
        bool isVersion;
        bool isDBGenerated; 
        bool isDiscriminator; 
        bool canBeNull = true;
        string dbType; 
        string expression;
        string mappedName;
        UpdateCheck updateCheck = UpdateCheck.Never;
        AutoSync autoSync = AutoSync.Never; 
        object locktarget = new object(); // Hold locks on private object rather than public MetaType.
        bool hasLoadMethod; 
        MethodInfo loadMethod; 

        internal MappedDataMember(MetaType declaringType, MemberInfo mi, MemberMapping map, int ordinal) { 
            this.declaringType = declaringType;
            this.member = mi;
            this.ordinal = ordinal;
            this.type = TypeSystem.GetMemberType(mi); 
            this.isNullableType = TypeSystem.IsNullableType(this.type);
            this.memberMap = map; 
            if (this.memberMap != null && this.memberMap.StorageMemberName != null) { 
                MemberInfo[] mis = mi.DeclaringType.GetMember(this.memberMap.StorageMemberName, BindingFlags.Instance | BindingFlags.NonPublic);
                if (mis == null || mis.Length != 1) { 
                    throw Error.BadStorageProperty(this.memberMap.StorageMemberName, mi.DeclaringType, mi.Name);
                }
                this.storageMember = mis[0];
            } 
            Type storageType = this.storageMember != null ? TypeSystem.GetMemberType(this.storageMember) : this.type;
            this.isDeferred = IsDeferredType(storageType); 
            ColumnMapping cmap = map as ColumnMapping; 
            if (cmap != null && cmap.IsDbGenerated && cmap.IsPrimaryKey) {
                // auto-gen identities must be synced on insert 
                if ((cmap.AutoSync != AutoSync.Default) && (cmap.AutoSync != AutoSync.OnInsert)) {
                    throw Error.IncorrectAutoSyncSpecification(mi.Name);
                }
            } 
            if (cmap != null) {
                this.isPrimaryKey = cmap.IsPrimaryKey; 
                this.isVersion = cmap.IsVersion; 
                this.isDBGenerated = cmap.IsDbGenerated || !string.IsNullOrEmpty(cmap.Expression) || this.isVersion;
                this.isDiscriminator = cmap.IsDiscriminator; 
                this.canBeNull = cmap.CanBeNull == null ? this.isNullableType || !this.type.IsValueType : (bool)cmap.CanBeNull;
                this.dbType = cmap.DbType;
                this.expression = cmap.Expression;
                this.updateCheck = cmap.UpdateCheck; 
                // auto-gen keys are always and only synced on insert
                if (this.IsDbGenerated && this.IsPrimaryKey) { 
                    this.autoSync = AutoSync.OnInsert; 
                }
                else if (cmap.AutoSync != AutoSync.Default) { 
                    // if the user has explicitly set it, use their value
                    this.autoSync = cmap.AutoSync;
                }
                else if (this.IsDbGenerated) { 
                    // database generated members default to always
                    this.autoSync = AutoSync.Always; 
                } 
            }
            this.mappedName = this.memberMap.DbName != null ? this.memberMap.DbName : this.member.Name; 
        }
        private void InitAccessors() {
            if (!this.hasAccessors) {
                lock (this.locktarget) { 
                    if (!this.hasAccessors) {
                        if (this.storageMember != null) { 
                            this.accPrivate = MakeMemberAccessor(this.member.ReflectedType, this.storageMember, null); 
                            if (this.isDeferred) {
                                MakeDeferredAccessors(this.member.ReflectedType, this.accPrivate, out this.accPrivate, out this.accDefValue, out this.accDefSource); 
                            }
                            this.accPublic = MakeMemberAccessor(this.member.ReflectedType, this.member, this.accPrivate);
                        }
                        else { 
                            this.accPublic = this.accPrivate = MakeMemberAccessor(this.member.ReflectedType, this.member, null);
                            if (this.isDeferred) { 
                                MakeDeferredAccessors(this.member.ReflectedType, this.accPrivate, out this.accPrivate, out this.accDefValue, out this.accDefSource); 
                            }
                        } 
                        this.hasAccessors = true;
                    }
                }
            } 
        }
        public override MetaType DeclaringType { 
            get { return this.declaringType; } 
        }
        public override bool IsDeclaredBy(MetaType metaType) { 
            if (metaType == null) {
                throw Error.ArgumentNull("metaType");
            }
            return metaType.Type == this.member.DeclaringType; 
        }
        public override MemberInfo Member { 
            get { return this.member; } 
        }
        public override MemberInfo StorageMember { 
            get { return this.storageMember; }
        }
        public override string Name {
            get { return this.member.Name; } 
        }
        public override int Ordinal { 
            get { return this.ordinal; } 
        }
        public override Type Type { 
            get { return this.type; }
        }
        public override MetaAccessor MemberAccessor {
            get { 
                this.InitAccessors();
                return this.accPublic; 
            } 
        }
        public override MetaAccessor StorageAccessor { 
            get {
                this.InitAccessors();
                return this.accPrivate;
            } 
        }
        public override MetaAccessor DeferredValueAccessor { 
            get { 
                this.InitAccessors();
                return this.accDefValue; 
            }
        }
        public override MetaAccessor DeferredSourceAccessor {
            get { 
                this.InitAccessors();
                return this.accDefSource; 
            } 
        }
        public override bool IsDeferred { 
            get { return this.isDeferred; }
        }
        public override bool IsPersistent {
            get { return this.memberMap != null; } 
        }
        public override bool IsAssociation { 
            get { return this.memberMap is AssociationMapping; } 
        }
        public override bool IsPrimaryKey { 
            get { return this.isPrimaryKey; }
        }
        /// 
        /// Returns true if the member is explicitly marked as auto gen, or if the 
        /// member is computed or generated by the database server.
        ///  
        public override bool IsDbGenerated { 
            get { return this.isDBGenerated; }
        } 
        public override bool IsVersion {
            get { return this.isVersion; }
        }
        public override bool IsDiscriminator { 
            get { return this.isDiscriminator; }
        } 
        public override bool CanBeNull { 
            get { return this.canBeNull; }
        } 
        public override string DbType {
            get { return this.dbType; }
        }
        public override string Expression { 
            get { return this.expression; }
        } 
        public override string MappedName { 
            get { return this.mappedName; }
        } 
        public override UpdateCheck UpdateCheck {
            get { return this.updateCheck; }
        }
        public override AutoSync AutoSync { 
            get { return this.autoSync; }
        } 
        public override MetaAssociation Association { 
            get {
                if (this.IsAssociation) { 
                    // LOCKING: This deferral isn't an optimization. It can't be done in the constructor
                    // because there may be loops in the association graph.
                    if (this.assoc == null) {
                        lock (this.locktarget) { 
                            if (this.assoc == null) {
                                this.assoc = new MappedAssociation(this, (AssociationMapping)this.memberMap); 
                            } 
                        }
                    } 
                }
                return this.assoc;
            }
        } 
        public override MethodInfo LoadMethod {
            get { 
                if (this.hasLoadMethod == false && this.IsDeferred) { 
                    // defer searching for this access method until we really need to know
                    this.loadMethod = MethodFinder.FindMethod( 
                        ((MappedMetaModel)this.declaringType.Model).ContextType,
                        "Load" + this.member.Name,
                        BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                        new Type[] { this.DeclaringType.Type } 
                        );
                    this.hasLoadMethod = true; 
                } 
                return this.loadMethod;
            } 
        }
        private bool IsDeferredType(Type clrType) {
            if (clrType == null || clrType == typeof(object)) {
                return false; 
            }
            if (clrType.IsGenericType) { 
                Type gtype = clrType.GetGenericTypeDefinition(); 
                return gtype == typeof(Link<>) ||
                    typeof(EntitySet<>).IsAssignableFrom(gtype) || 
                    typeof(EntityRef<>).IsAssignableFrom(gtype) ||
                    IsDeferredType(clrType.BaseType);
            }
            return false; 
        }
        private static MetaAccessor MakeMemberAccessor(Type accessorType, MemberInfo mi, MetaAccessor storage) { 
            FieldInfo fi = mi as FieldInfo; 
            MetaAccessor acc = null;
            if (fi != null) { 
                acc = FieldAccessor.Create(accessorType, fi);
            }
            else {
                PropertyInfo pi = (PropertyInfo)mi; 
                acc = PropertyAccessor.Create(accessorType, pi, storage);
            } 
            return acc; 
        }
        private static void MakeDeferredAccessors( 
            Type declaringType, MetaAccessor accessor,
            out MetaAccessor accessorValue, out MetaAccessor accessorDeferredValue, out MetaAccessor accessorDeferredSource
            ) {
            if (accessor.Type.IsGenericType) { 
                Type gtype = accessor.Type.GetGenericTypeDefinition();
                Type itemType = accessor.Type.GetGenericArguments()[0]; 
                if (gtype == typeof(Link<>)) { 
                    accessorValue = CreateAccessor(typeof(LinkValueAccessor<,>).MakeGenericType(declaringType, itemType), accessor);
                    accessorDeferredValue = CreateAccessor(typeof(LinkDefValueAccessor<,>).MakeGenericType(declaringType, itemType), accessor); 
                    accessorDeferredSource = CreateAccessor(typeof(LinkDefSourceAccessor<,>).MakeGenericType(declaringType, itemType), accessor);
                    return;
                }
                else if (typeof(EntityRef<>).IsAssignableFrom(gtype)) { 
                    accessorValue = CreateAccessor(typeof(EntityRefValueAccessor<,>).MakeGenericType(declaringType, itemType), accessor);
                    accessorDeferredValue = CreateAccessor(typeof(EntityRefDefValueAccessor<,>).MakeGenericType(declaringType, itemType), accessor); 
                    accessorDeferredSource = CreateAccessor(typeof(EntityRefDefSourceAccessor<,>).MakeGenericType(declaringType, itemType), accessor); 
                    return;
                } 
                else if (typeof(EntitySet<>).IsAssignableFrom(gtype)) {
                    accessorValue = CreateAccessor(typeof(EntitySetValueAccessor<,>).MakeGenericType(declaringType, itemType), accessor);
                    accessorDeferredValue = CreateAccessor(typeof(EntitySetDefValueAccessor<,>).MakeGenericType(declaringType, itemType), accessor);
                    accessorDeferredSource = CreateAccessor(typeof(EntitySetDefSourceAccessor<,>).MakeGenericType(declaringType, itemType), accessor); 
                    return;
                } 
            } 
            throw Error.UnhandledDeferredStorageType(accessor.Type);
        } 
        private static MetaAccessor CreateAccessor(Type accessorType, params object[] args) {
            return (MetaAccessor)Activator.CreateInstance(accessorType, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, args, null);
        }
    } 

    internal class MappedAssociation : MetaAssociationImpl { 
        MappedDataMember thisMember; 
        MetaDataMember otherMember;
        MetaType otherType; 
        ReadOnlyCollection thisKey;
        ReadOnlyCollection otherKey;
        bool isMany;
        bool isForeignKey; 
        bool isNullable;
        bool thisKeyIsPrimaryKey; 
        bool otherKeyIsPrimaryKey; 
        AssociationMapping assocMap;
 
        internal MappedAssociation(MappedDataMember mm, AssociationMapping assocMap) {
            this.thisMember = mm;
            this.assocMap = assocMap;
            this.Init(); 
            this.InitOther();
            //validate the number of ThisKey columns is the same as the number of OtherKey columns 
            if (this.thisKey.Count != this.otherKey.Count && this.thisKey.Count > 0 && this.otherKey.Count > 0) { 
                throw Error.MismatchedThisKeyOtherKey(thisMember.Name, thisMember.DeclaringType.Name);
            } 
        }
        #region Initialization
        private void Init() {
            this.isMany = TypeSystem.IsSequenceType(this.thisMember.Type); 
            this.thisKey = (this.assocMap.ThisKey != null)
                ? MakeKeys(this.thisMember.DeclaringType, this.assocMap.ThisKey) 
                : this.thisMember.DeclaringType.IdentityMembers; 
            // this association refers to the parent if thisKey is not our own identity
            this.thisKeyIsPrimaryKey = AreEqual(this.thisKey, this.thisMember.DeclaringType.IdentityMembers); 
            this.isForeignKey = this.assocMap.IsForeignKey;

            // if any key members are not nullable, the association is not nullable
            this.isNullable = true; 
            foreach (MetaDataMember mm in this.thisKey) {
                if (mm == null) 
                    throw Error.UnexpectedNull("MetaDataMember"); 

                if (!mm.CanBeNull) { 
                    this.isNullable = false;
                    break;
                }
            } 

            // validate DeleteOnNull specification 
            if (assocMap.DeleteOnNull == true) { 
                if (!(isForeignKey && !isMany && !isNullable)) {
                    throw Error.InvalidDeleteOnNullSpecification(thisMember); 
                }
            }
        }
        private void InitOther() { 
            if (this.otherType == null) {
                Type ot = this.isMany ? TypeSystem.GetElementType(this.thisMember.Type) : this.thisMember.Type; 
                this.otherType = this.thisMember.DeclaringType.Model.GetMetaType(ot); 
                System.Diagnostics.Debug.Assert(this.otherType.IsEntity);
                this.otherKey = (assocMap.OtherKey != null) 
                    ? MakeKeys(this.otherType, this.assocMap.OtherKey)
                    : this.otherType.IdentityMembers;
                this.otherKeyIsPrimaryKey = AreEqual(this.otherKey, this.otherType.IdentityMembers);
                foreach (MetaDataMember omm in this.otherType.DataMembers) { 
                    if (omm.IsAssociation && omm != this.thisMember && omm.MappedName == this.thisMember.MappedName) {
                        this.otherMember = omm; 
                        break; 
                    }
                } 
            }
        }
        #endregion
        public override MetaDataMember ThisMember { 
            get { return this.thisMember; }
        } 
        public override ReadOnlyCollection ThisKey { 
            get { return this.thisKey; }
        } 
        public override MetaDataMember OtherMember {
            get { return this.otherMember; }
        }
        public override ReadOnlyCollection OtherKey { 
            get { return this.otherKey; }
        } 
        public override MetaType OtherType { 
            get { return this.otherType; }
        } 
        public override bool IsMany {
            get { return this.isMany; }
        }
        public override bool IsForeignKey { 
            get { return this.isForeignKey; }
        } 
        public override bool IsUnique { 
            get { return this.assocMap.IsUnique; }
        } 
        public override bool IsNullable {
            get { return this.isNullable; }
        }
        public override bool ThisKeyIsPrimaryKey { 
            get { return this.thisKeyIsPrimaryKey; }
        } 
        public override bool OtherKeyIsPrimaryKey { 
            get { return this.otherKeyIsPrimaryKey; }
        } 
        public override string DeleteRule {
            get {
                return this.assocMap.DeleteRule;
            } 
        }
        public override bool DeleteOnNull { 
            get { 
                return this.assocMap.DeleteOnNull;
            } 
        }
    }

    class MappedFunction : MetaFunction { 
        MetaModel model;
        FunctionMapping map; 
        MethodInfo method; 
        ReadOnlyCollection parameters;
        MetaParameter returnParameter; 
        ReadOnlyCollection rowTypes;
        static ReadOnlyCollection _emptyParameters = new List(0).AsReadOnly();
        static ReadOnlyCollection _emptyTypes = new List(0).AsReadOnly();
 
        internal MappedFunction(MappedMetaModel model, FunctionMapping map, MethodInfo method) {
            this.model = model; 
            this.map = map; 
            this.method = method;
            this.rowTypes = _emptyTypes; 

            if (map.Types.Count == 0 && this.method.ReturnType == typeof(IMultipleResults)) {
                throw Error.NoResultTypesDeclaredForFunction(method.Name);
            } 
            else if (map.Types.Count > 1 && this.method.ReturnType != typeof(IMultipleResults)) {
                throw Error.TooManyResultTypesDeclaredForFunction(method.Name); 
            } 
            else if (map.Types.Count == 1 && this.method.ReturnType != typeof(IMultipleResults)) {
                Type elementType = TypeSystem.GetElementType(method.ReturnType); 
                this.rowTypes = new List(1) { this.GetMetaType(map.Types[0], elementType) }.AsReadOnly();
            }
            else if (map.Types.Count > 0) {
                List rowTypes = new List(); 
                foreach (TypeMapping rtm in map.Types) {
                    Type elementType = model.FindType(rtm.Name); 
                    if (elementType == null) { 
                        throw Error.CouldNotFindElementTypeInModel(rtm.Name);
                    } 
                    MetaType mt = this.GetMetaType(rtm, elementType);
                    // Only add unique meta types
                    if (!rowTypes.Contains(mt)) {
                        rowTypes.Add(mt); 
                    }
                } 
                this.rowTypes = rowTypes.AsReadOnly(); 
            }
            else if (map.FunReturn != null) { 
                this.returnParameter = new MappedReturnParameter(method.ReturnParameter, map.FunReturn);
            }

            // Parameters. 
            ParameterInfo[] pis = this.method.GetParameters();
            if (pis.Length > 0) { 
                List mps = new List(pis.Length); 
                if (this.map.Parameters.Count != pis.Length) {
                    throw Error.IncorrectNumberOfParametersMappedForMethod(this.map.MethodName); 
                }
                for (int i = 0; i < pis.Length; i++) {
                    mps.Add(new MappedParameter(pis[i], this.map.Parameters[i]));
                } 
                this.parameters = mps.AsReadOnly();
            } 
            else { 
                this.parameters = _emptyParameters;
            } 
        }
        /// 
        /// For the specified type, if it is a mapped type, use the Table
        /// metatype to get the correct inheritance metatype, 
        /// otherwise create a new meta type.
        private MetaType GetMetaType(TypeMapping tm, Type elementType) { 
            MetaTable tbl = model.GetTable(elementType); 
            if (tbl != null) {
                return tbl.RowType.GetInheritanceType(elementType); 
            }
            return new MappedRootType((MappedMetaModel)model, null, tm, elementType);
        }
        public override ReadOnlyCollection Parameters { 
            get { return this.parameters; }
        } 
        public override string MappedName { 
            get { return this.map.Name; }
        } 
        public override MethodInfo Method {
            get { return this.method; }
        }
        public override MetaModel Model { 
            get { return this.model; }
        } 
        public override string Name { 
            get { return this.method.Name; }
        } 
        public override bool IsComposable {
            get { return this.map.IsComposable; }
        }
        public override MetaParameter ReturnParameter { 
            get { return this.returnParameter; }
        } 
        public override bool HasMultipleResults { 
            get { return this.method.ReturnType == typeof(IMultipleResults); }
        } 
        public override ReadOnlyCollection ResultRowTypes {
            get { return this.rowTypes; }
        }
    } 

    internal sealed class MappedParameter : MetaParameter { 
        private ParameterInfo parameterInfo; 
        private ParameterMapping map;
 
        public MappedParameter(ParameterInfo parameterInfo, ParameterMapping map) {
            this.parameterInfo = parameterInfo;
            this.map = map;
        } 
        public override ParameterInfo Parameter {
            get { return this.parameterInfo; } 
        } 
        public override string Name {
            get { return this.parameterInfo.Name; } 
        }
        public override string MappedName {
            get { return this.map.Name; }
        } 
        public override Type ParameterType {
            get { return this.parameterInfo.ParameterType; } 
        } 
        public override string DbType {
            get { return this.map.DbType; } 
        }
    }

    internal sealed class MappedReturnParameter : MetaParameter { 
        private ParameterInfo parameterInfo;
        private ReturnMapping map; 
 
        public MappedReturnParameter(ParameterInfo parameterInfo, ReturnMapping map) {
            this.parameterInfo = parameterInfo; 
            this.map = map;
        }
        public override ParameterInfo Parameter {
            get { return this.parameterInfo; } 
        }
        public override string Name { 
            get { return null; } 
        }
        public override string MappedName { 
            get { return null; }
        }
        public override Type ParameterType {
            get { return this.parameterInfo.ParameterType; } 
        }
        public override string DbType { 
            get { return this.map.DbType; } 
        }
    } 

    internal abstract class MetaAssociationImpl : MetaAssociation {

        private static char[] keySeparators = new char[] { ',' }; 
        /// 
        /// Given a MetaType and a set of key fields, return the set of MetaDataMembers 
        /// corresponding to the key. 
        /// 
        protected static ReadOnlyCollection MakeKeys(MetaType mtype, string keyFields) { 
            string[] names = keyFields.Split(keySeparators);
            MetaDataMember[] members = new MetaDataMember[names.Length];
            for (int i = 0; i < names.Length; i++) {
                names[i] = names[i].Trim(); 
                MemberInfo[] rmis = mtype.Type.GetMember(names[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
                if (rmis == null || rmis.Length != 1) { 
                    throw Error.BadKeyMember(names[i], keyFields, mtype.Name); 
                }
                members[i] = mtype.GetDataMember(rmis[0]); 
                if (members[i] == null) {
                    throw Error.BadKeyMember(names[i], keyFields, mtype.Name);
                }
            } 
            return new List(members).AsReadOnly();
        } 
 
        /// 
        /// Compare two sets of keys for equality. 
        /// 
        protected static bool AreEqual(IEnumerable key1, IEnumerable key2) {
            using (IEnumerator e1 = key1.GetEnumerator()) {
                using (IEnumerator e2 = key2.GetEnumerator()) { 
                    bool m1, m2;
                    for (m1 = e1.MoveNext(), m2 = e2.MoveNext(); m1 && m2; m1 = e1.MoveNext(), m2 = e2.MoveNext()) { 
                        if (e1.Current != e2.Current) 
                            return false;
                    } 
                    if (m1 != m2)
                        return false;
                }
            } 
            return true;
        } 
 
        public override string ToString() {
            return string.Format(Globalization.CultureInfo.InvariantCulture, "{0} ->{1} {2}", ThisMember.DeclaringType.Name, IsMany ? "*" : "", OtherType.Name); 
        }
    }

    internal sealed class UnmappedType : MetaType { 
        MetaModel model;
        Type type; 
        Dictionary dataMemberMap; 
        ReadOnlyCollection dataMembers;
        ReadOnlyCollection inheritanceTypes; 
        object locktarget = new object(); // Hold locks on private object rather than public MetaType.

        private static ReadOnlyCollection _emptyTypes = new List().AsReadOnly();
        private static ReadOnlyCollection _emptyDataMembers = new List().AsReadOnly(); 
        private static ReadOnlyCollection _emptyAssociations = new List().AsReadOnly();
 
        internal UnmappedType(MetaModel model, Type type) { 
            this.model = model;
            this.type = type; 
        }

        public override MetaModel Model {
            get { return this.model; } 
        }
        public override MetaTable Table { 
            get { return null; } 
        }
        public override Type Type { 
            get { return this.type; }
        }
        public override string Name {
            get { return this.type.Name; } 
        }
        public override bool IsEntity { 
            get { return false; } 
        }
        public override bool CanInstantiate { 
            get { return !this.type.IsAbstract; }
        }
        public override MetaDataMember DBGeneratedIdentityMember {
            get { return null; } 
        }
        public override MetaDataMember VersionMember { 
            get { return null; } 
        }
        public override MetaDataMember Discriminator { 
            get { return null; }
        }
        public override bool HasUpdateCheck {
            get { return false; } 
        }
        public override ReadOnlyCollection InheritanceTypes { 
            get { 
                if (this.inheritanceTypes == null) {
                    lock (this.locktarget) { 
                        if (this.inheritanceTypes == null) {
                            this.inheritanceTypes = new MetaType[] { this }.ToList().AsReadOnly();
                        }
                    } 
                }
                return this.inheritanceTypes; 
            } 
        }
        public override MetaType GetInheritanceType(Type inheritanceType) { 
            if (inheritanceType == this.type)
                return this;
            return null;
        } 
        public override ReadOnlyCollection DerivedTypes {
            get { return _emptyTypes; } 
        } 
        public override MetaType GetTypeForInheritanceCode(object key) {
            return null; 
        }
        public override bool HasInheritance {
            get { return false; }
        } 
        public override bool HasInheritanceCode {
            get { return false; } 
        } 
        public override object InheritanceCode {
            get { return null; } 
        }
        public override MetaType InheritanceRoot {
            get { return this; }
        } 
        public override MetaType InheritanceBase {
            get { return null; } 
        } 
        public override MetaType InheritanceDefault {
            get { return null; } 
        }
        public override bool IsInheritanceDefault {
            get { return false; }
        } 
        public override ReadOnlyCollection DataMembers {
            get { 
                this.InitDataMembers(); 
                return this.dataMembers;
            } 
        }
        public override ReadOnlyCollection PersistentDataMembers {
            get { return _emptyDataMembers; }
        } 
        public override ReadOnlyCollection IdentityMembers {
            get { 
                this.InitDataMembers(); 
                return this.dataMembers;
            } 
        }
        public override ReadOnlyCollection Associations {
            get { return _emptyAssociations; }
        } 
        public override MetaDataMember GetDataMember(MemberInfo mi) {
            if (mi == null) 
                throw Error.ArgumentNull("mi"); 
            this.InitDataMembers();
            if (this.dataMemberMap == null) { 
                lock (this.locktarget) {
                    if (this.dataMemberMap == null) {
                        Dictionary map = new Dictionary();
                        foreach (MetaDataMember mm in this.dataMembers) { 
                            map.Add(InheritanceRules.DistinguishedMemberName(mm.Member), mm);
                        } 
                        this.dataMemberMap = map; 
                    }
                } 
            }
            object dn = InheritanceRules.DistinguishedMemberName(mi);
            MetaDataMember mdm;
            this.dataMemberMap.TryGetValue(dn, out mdm); 
            return mdm;
        } 
 
        private void InitDataMembers() {
            if (this.dataMembers == null) { 
                lock (this.locktarget) {
                    if (this.dataMembers == null) {
                        List dMembers = new List();
                        int ordinal = 0; 
                        BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
                        foreach (FieldInfo fi in this.type.GetFields(flags)) { 
                            MetaDataMember mm = new UnmappedDataMember(this, fi, ordinal); 
                            dMembers.Add(mm);
                            ordinal++; 
                        }
                        foreach (PropertyInfo pi in this.type.GetProperties(flags)) {
                            MetaDataMember mm = new UnmappedDataMember(this, pi, ordinal);
                            dMembers.Add(mm); 
                            ordinal++;
                        } 
                        this.dataMembers = dMembers.AsReadOnly(); 
                    }
                } 
            }
        }

        public override string ToString() { 
            return this.Name;
        } 
 
        public override MethodInfo OnLoadedMethod {
            get { return null; } 
        }

        public override MethodInfo OnValidateMethod {
            get { return null; } 
        }
        public override bool HasAnyValidateMethod { 
            get { 
                return false;
            } 
        }
        public override bool HasAnyLoadMethod {
            get {
                return false; 
            }
        } 
    } 

    internal sealed class UnmappedDataMember : MetaDataMember { 
        MetaType declaringType;
        MemberInfo member;
        int ordinal;
        Type type; 
        MetaAccessor accPublic;
        object lockTarget = new object(); 
 
        internal UnmappedDataMember(MetaType declaringType, MemberInfo mi, int ordinal) {
            this.declaringType = declaringType; 
            this.member = mi;
            this.ordinal = ordinal;
            this.type = TypeSystem.GetMemberType(mi);
        } 
        private void InitAccessors() {
            if (this.accPublic == null) { 
                lock (this.lockTarget) { 
                    if (this.accPublic == null) {
                        this.accPublic = MakeMemberAccessor(this.member.ReflectedType, this.member); 
                    }
                }
            }
        } 
        public override MetaType DeclaringType {
            get { return this.declaringType; } 
        } 
        public override bool IsDeclaredBy(MetaType metaType) {
            if (metaType == null) { 
                throw Error.ArgumentNull("metaType");
            }
            return metaType.Type == this.member.DeclaringType;
        } 
        public override MemberInfo Member {
            get { return this.member; } 
        } 
        public override MemberInfo StorageMember {
            get { return this.member; } 
        }
        public override string Name {
            get { return this.member.Name; }
        } 
        public override int Ordinal {
            get { return this.ordinal; } 
        } 
        public override Type Type {
            get { return this.type; } 
        }
        public override MetaAccessor MemberAccessor {
            get {
                this.InitAccessors(); 
                return this.accPublic;
            } 
        } 
        public override MetaAccessor StorageAccessor {
            get { 
                this.InitAccessors();
                return this.accPublic;
            }
        } 
        public override MetaAccessor DeferredValueAccessor {
            get { return null; } 
        } 
        public override MetaAccessor DeferredSourceAccessor {
            get { return null; } 
        }
        public override bool IsDeferred {
            get { return false; }
        } 
        public override bool IsPersistent {
            get { return false; } 
        } 
        public override bool IsAssociation {
            get { return false; } 
        }
        public override bool IsPrimaryKey {
            get { return false; }
        } 
        public override bool IsDbGenerated {
            get { return false; } 
        } 
        public override bool IsVersion {
            get { return false; } 
        }
        public override bool IsDiscriminator {
            get { return false; }
        } 
        public override bool CanBeNull {
            get { return !this.type.IsValueType || TypeSystem.IsNullableType(this.type); } 
        } 
        public override string DbType {
            get { return null; } 
        }
        public override string Expression {
            get { return null; }
        } 
        public override string MappedName {
            get { return this.member.Name; } 
        } 
        public override UpdateCheck UpdateCheck {
            get { return UpdateCheck.Never; } 
        }
        public override AutoSync AutoSync {
            get { return AutoSync.Never; }
        } 
        public override MetaAssociation Association {
            get { return null; } 
        } 
        public override MethodInfo LoadMethod {
            get { return null; } 
        }
        private static MetaAccessor MakeMemberAccessor(Type accessorType, MemberInfo mi) {
            FieldInfo fi = mi as FieldInfo;
            MetaAccessor acc = null; 
            if (fi != null) {
                acc = FieldAccessor.Create(accessorType, fi); 
            } 
            else {
                PropertyInfo pi = (PropertyInfo)mi; 
                acc = PropertyAccessor.Create(accessorType, pi, null);
            }
            return acc;
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

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