Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DLinq / Dlinq / Mapping / MappingSource.cs / 1305376 / MappingSource.cs
using System; using System.Collections.ObjectModel; using System.Collections.Generic; using System.Linq.Expressions; using System.Linq; using System.Reflection; using System.Runtime.Versioning; using System.Text; using System.Threading; using System.Xml; using System.Xml.Serialization; using LinqToSqlShared.Mapping; namespace System.Data.Linq.Mapping { using System.Data.Linq.Provider; using System.Diagnostics.CodeAnalysis; ////// Represents a source for mapping information. /// public abstract class MappingSource { MetaModel primaryModel; ReaderWriterLock rwlock; DictionarysecondaryModels; /// /// Gets the MetaModel representing a DataContext and all it's /// accessible tables, functions and entities. /// public MetaModel GetModel(Type dataContextType) { if (dataContextType == null) { throw Error.ArgumentNull("dataContextType"); } MetaModel model = null; if (this.primaryModel == null) { model = this.CreateModel(dataContextType); Interlocked.CompareExchange(ref this.primaryModel, model, null); } // if the primary one matches, use it! if (this.primaryModel.ContextType == dataContextType) { return this.primaryModel; } // the rest of this only happens if you are using the mapping source for // more than one context type // build a map if one is not already defined if (this.secondaryModels == null) { Interlocked.CompareExchange >(ref this.secondaryModels, new Dictionary (), null); } // if we haven't created a read/writer lock, make one now if (this.rwlock == null) { Interlocked.CompareExchange (ref this.rwlock, new ReaderWriterLock(), null); } // lock the map and look inside MetaModel foundModel; this.rwlock.AcquireReaderLock(Timeout.Infinite); try { if (this.secondaryModels.TryGetValue(dataContextType, out foundModel)) { return foundModel; } } finally { this.rwlock.ReleaseReaderLock(); } // if it wasn't found, lock for write and try again this.rwlock.AcquireWriterLock(Timeout.Infinite); try { if (this.secondaryModels.TryGetValue(dataContextType, out foundModel)) { return foundModel; } if (model == null) { model = this.CreateModel(dataContextType); } this.secondaryModels.Add(dataContextType, model); } finally { this.rwlock.ReleaseWriterLock(); } return model; } /// /// Creates a new instance of a MetaModel. This method is called by GetModel(). /// Override this method when defining a new type of MappingSource. /// /// ///protected abstract MetaModel CreateModel(Type dataContextType); } /// /// A mapping source that uses attributes on the context to create the mapping model. /// public sealed class AttributeMappingSource : MappingSource { public AttributeMappingSource() { } protected override MetaModel CreateModel(Type dataContextType) { if (dataContextType == null) { throw Error.ArgumentNull("dataContextType"); } return new AttributedMetaModel(this, dataContextType); } } ////// A mapping source that uses an external XML mapping source to create the model. /// public sealed class XmlMappingSource : MappingSource { DatabaseMapping map; [ResourceExposure(ResourceScope.Assembly)] // map parameter contains type names. private XmlMappingSource(DatabaseMapping map) { this.map = map; } [ResourceExposure(ResourceScope.None)] // Exposure is via map instance variable. [ResourceConsumption(ResourceScope.Assembly | ResourceScope.Machine, ResourceScope.Assembly | ResourceScope.Machine)] // For MappedMetaModel constructor call. protected override MetaModel CreateModel(Type dataContextType) { if (dataContextType == null) { throw Error.ArgumentNull("dataContextType"); } return new MappedMetaModel(this, dataContextType, this.map); } ////// Create a mapping source from xml string. /// /// The type of DataContext to base the mapping on. /// A string containing XML. ///The mapping source. [ResourceExposure(ResourceScope.Assembly)] // Xml contains type names. [ResourceConsumption(ResourceScope.Assembly)] // For FromReader method call. public static XmlMappingSource FromXml(string xml) { if (xml == null) { throw Error.ArgumentNull("xml"); } XmlReader reader = new XmlTextReader(new System.IO.StringReader(xml)); return FromReader(reader); } ////// Create a mapping source from xml reader. /// /// The type of DataContext to base the mapping on. /// An xml reader. ///The mapping source. [ResourceExposure(ResourceScope.Assembly)] // reader parameter contains type names. [ResourceConsumption(ResourceScope.Assembly)] // XmlMappingSource constructor call. public static XmlMappingSource FromReader(XmlReader reader) { if (reader == null) { throw Error.ArgumentNull("reader"); } reader.MoveToContent(); DatabaseMapping db = XmlMappingReader.ReadDatabaseMapping(reader); if (db == null) { throw Error.DatabaseNodeNotFound(XmlMappingConstant.MappingNamespace); } return new XmlMappingSource(db); } ////// Create a mapping source from xml in a stream. /// /// The type of DataContext to base the mapping on. /// A stream of xml. ///The mapping source. [ResourceExposure(ResourceScope.Assembly)] // Stream contains type names. [ResourceConsumption(ResourceScope.Assembly)] // For FromReader method call. public static XmlMappingSource FromStream(System.IO.Stream stream) { if (stream == null) { throw Error.ArgumentNull("stream"); } XmlReader reader = new XmlTextReader(stream); return FromReader(reader); } ////// Create a mapping source from xml loaded from a url. /// /// The type of DataContext to base the mapping on. /// The Url pointing to the xml. ///The mapping source. [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#", Justification="Unknown reason.")] [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)] // url parameter which may contain type names. [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly)] // XmlTextReader constructor & FromReader method call. public static XmlMappingSource FromUrl(string url) { if (url == null) { throw Error.ArgumentNull("url"); } XmlReader reader = new XmlTextReader(url); try { return FromReader(reader); } finally { reader.Close(); } } } class XmlMappingReader { private static string RequiredAttribute(XmlReader reader, string attribute) { string result = OptionalAttribute(reader, attribute); if (result == null) { throw Error.CouldNotFindRequiredAttribute(attribute, reader.ReadOuterXml()); } return result; } private static string OptionalAttribute(XmlReader reader, string attribute) { return reader.GetAttribute(attribute); } private static bool OptionalBoolAttribute(XmlReader reader, string attribute, bool @default) { string value = OptionalAttribute(reader, attribute); return (value != null) ? bool.Parse(value) : @default; } private static bool? OptionalNullableBoolAttribute(XmlReader reader, string attribute) { string value = OptionalAttribute(reader, attribute); return (value != null) ? (bool?)bool.Parse(value) : null; } private static void AssertEmptyElement(XmlReader reader) { if (!reader.IsEmptyElement) { string nodeName = reader.Name; reader.Read(); if (reader.NodeType != XmlNodeType.EndElement) { throw Error.ExpectedEmptyElement(nodeName, reader.NodeType, reader.Name); } } reader.Skip(); } internal static DatabaseMapping ReadDatabaseMapping(XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Database) { return null; } ValidateAttributes(reader, new[] { XmlMappingConstant.Name, XmlMappingConstant.Provider }); DatabaseMapping dm = new DatabaseMapping(); dm.DatabaseName = RequiredAttribute(reader, XmlMappingConstant.Name); dm.Provider = OptionalAttribute(reader, XmlMappingConstant.Provider); if (!reader.IsEmptyElement) { reader.ReadStartElement(); reader.MoveToContent(); while (reader.NodeType != XmlNodeType.EndElement) { if (reader.NodeType == XmlNodeType.Whitespace || !IsInNamespace(reader)) { reader.Skip(); continue; } switch (reader.LocalName) { case XmlMappingConstant.Table: dm.Tables.Add(ReadTableMapping(reader)); break; case XmlMappingConstant.Function: dm.Functions.Add(ReadFunctionMapping(reader)); break; default: throw Error.UnrecognizedElement(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } reader.MoveToContent(); } if (reader.LocalName != XmlMappingConstant.Database) { throw Error.UnexpectedElement(XmlMappingConstant.Database, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } reader.ReadEndElement(); } else { System.Diagnostics.Debug.Assert(false, "DatabaseMapping has no content"); reader.Skip(); } return dm; } internal static bool IsInNamespace(XmlReader reader) { return reader.LookupNamespace(reader.Prefix) == XmlMappingConstant.MappingNamespace; } internal static void ValidateAttributes(XmlReader reader, string[] validAttributes) { if (reader.HasAttributes) { ListattrList = new List (validAttributes); const string xmlns = "xmlns"; for (int i = 0; i < reader.AttributeCount; i++) { reader.MoveToAttribute(i); // if the node's in the namespace, it is required to be one of the valid ones if (IsInNamespace(reader) && reader.LocalName != xmlns && !attrList.Contains(reader.LocalName)) { throw Error.UnrecognizedAttribute(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : ":", reader.LocalName)); } } reader.MoveToElement(); // Moves the reader back to the element node. } } internal static FunctionMapping ReadFunctionMapping(XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Function) { throw Error.UnexpectedElement(XmlMappingConstant.Function, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } ValidateAttributes(reader, new[] { XmlMappingConstant.Name, XmlMappingConstant.Method, XmlMappingConstant.IsComposable }); FunctionMapping fm = new FunctionMapping(); fm.MethodName = RequiredAttribute(reader, XmlMappingConstant.Method); fm.Name = OptionalAttribute(reader, XmlMappingConstant.Name); fm.IsComposable = OptionalBoolAttribute(reader, XmlMappingConstant.IsComposable, false); if (!reader.IsEmptyElement) { reader.ReadStartElement(); reader.MoveToContent(); while (reader.NodeType != XmlNodeType.EndElement) { if (reader.NodeType == XmlNodeType.Whitespace || !IsInNamespace(reader)) { reader.Skip(); continue; } switch (reader.LocalName) { case XmlMappingConstant.Parameter: fm.Parameters.Add(ReadParameterMapping(reader)); break; case XmlMappingConstant.ElementType: fm.Types.Add(ReadElementTypeMapping(null, reader)); break; case XmlMappingConstant.Return: fm.FunReturn = ReadReturnMapping(reader); break; default: throw Error.UnrecognizedElement(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } reader.MoveToContent(); } reader.ReadEndElement(); } else { // no content is okay reader.Skip(); } return fm; } private static ReturnMapping ReadReturnMapping(XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Return) { throw Error.UnexpectedElement(XmlMappingConstant.Return, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } ValidateAttributes(reader, new[] { XmlMappingConstant.DbType }); ReturnMapping rm = new ReturnMapping(); rm.DbType = OptionalAttribute(reader, XmlMappingConstant.DbType); AssertEmptyElement(reader); return rm; } private static ParameterMapping ReadParameterMapping(XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Parameter) { throw Error.UnexpectedElement(XmlMappingConstant.Parameter, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } ValidateAttributes(reader, new[] { XmlMappingConstant.Name, XmlMappingConstant.DbType, XmlMappingConstant.Parameter, XmlMappingConstant.Direction }); ParameterMapping pm = new ParameterMapping(); pm.Name = RequiredAttribute(reader, XmlMappingConstant.Name); pm.ParameterName = RequiredAttribute(reader, XmlMappingConstant.Parameter); pm.DbType = OptionalAttribute(reader, XmlMappingConstant.DbType); pm.XmlDirection = OptionalAttribute(reader, XmlMappingConstant.Direction); AssertEmptyElement(reader); return pm; } private static TableMapping ReadTableMapping(XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Table) { throw Error.UnexpectedElement(XmlMappingConstant.Table, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } ValidateAttributes(reader, new[] { XmlMappingConstant.Name, XmlMappingConstant.Member }); TableMapping tm = new TableMapping(); tm.TableName = OptionalAttribute(reader, XmlMappingConstant.Name); tm.Member = OptionalAttribute(reader, XmlMappingConstant.Member); if (!reader.IsEmptyElement) { reader.ReadStartElement(); reader.MoveToContent(); while (reader.NodeType != XmlNodeType.EndElement) { if (reader.NodeType == XmlNodeType.Whitespace || !IsInNamespace(reader)) { reader.Skip(); continue; } switch (reader.LocalName) { case XmlMappingConstant.Type: if (tm.RowType != null) { goto default; } tm.RowType = ReadTypeMapping(null, reader); break; default: throw Error.UnrecognizedElement(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } reader.MoveToContent(); } if (reader.LocalName != XmlMappingConstant.Table) { throw Error.UnexpectedElement(XmlMappingConstant.Table, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } reader.ReadEndElement(); } else { System.Diagnostics.Debug.Assert(false, "Table has no content"); reader.Skip(); } return tm; } private static TypeMapping ReadElementTypeMapping(TypeMapping baseType, XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.ElementType) { throw Error.UnexpectedElement(XmlMappingConstant.Type, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } return ReadTypeMappingImpl(baseType, reader); } private static TypeMapping ReadTypeMapping(TypeMapping baseType, XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Type) { throw Error.UnexpectedElement(XmlMappingConstant.Type, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } return ReadTypeMappingImpl(baseType, reader); } private static TypeMapping ReadTypeMappingImpl(TypeMapping baseType, XmlReader reader) { ValidateAttributes(reader, new[] { XmlMappingConstant.Name, XmlMappingConstant.InheritanceCode, XmlMappingConstant.IsInheritanceDefault }); TypeMapping tm = new TypeMapping(); tm.BaseType = baseType; tm.Name = RequiredAttribute(reader, XmlMappingConstant.Name); tm.InheritanceCode = OptionalAttribute(reader, XmlMappingConstant.InheritanceCode); tm.IsInheritanceDefault = OptionalBoolAttribute(reader, XmlMappingConstant.IsInheritanceDefault, false); if (!reader.IsEmptyElement) { reader.ReadStartElement(); reader.MoveToContent(); while (reader.NodeType != XmlNodeType.EndElement) { if (reader.NodeType == XmlNodeType.Whitespace || !IsInNamespace(reader)) { reader.Skip(); continue; } switch (reader.LocalName) { case XmlMappingConstant.Type: tm.DerivedTypes.Add(ReadTypeMapping(tm, reader)); break; case XmlMappingConstant.Association: tm.Members.Add(ReadAssociationMapping(reader)); break; case XmlMappingConstant.Column: tm.Members.Add(ReadColumnMapping(reader)); break; default: throw Error.UnrecognizedElement(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } reader.MoveToContent(); } reader.ReadEndElement(); } else { // no content is okay reader.Skip(); } return tm; } private static AssociationMapping ReadAssociationMapping(XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Association) { throw Error.UnexpectedElement(XmlMappingConstant.Association, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } ValidateAttributes(reader, new[] { XmlMappingConstant.Name, XmlMappingConstant.IsForeignKey, XmlMappingConstant.IsUnique, XmlMappingConstant.Member, XmlMappingConstant.OtherKey, XmlMappingConstant.Storage, XmlMappingConstant.ThisKey, XmlMappingConstant.DeleteRule, XmlMappingConstant.DeleteOnNull, }); AssociationMapping am = new AssociationMapping(); am.DbName = OptionalAttribute(reader, XmlMappingConstant.Name); am.IsForeignKey = OptionalBoolAttribute(reader, XmlMappingConstant.IsForeignKey, false); am.IsUnique = OptionalBoolAttribute(reader, XmlMappingConstant.IsUnique, false); am.MemberName = RequiredAttribute(reader, XmlMappingConstant.Member); am.OtherKey = OptionalAttribute(reader, XmlMappingConstant.OtherKey); am.StorageMemberName = OptionalAttribute(reader, XmlMappingConstant.Storage); am.ThisKey = OptionalAttribute(reader, XmlMappingConstant.ThisKey); am.DeleteRule = OptionalAttribute(reader, XmlMappingConstant.DeleteRule); am.DeleteOnNull = OptionalBoolAttribute(reader, XmlMappingConstant.DeleteOnNull, false); AssertEmptyElement(reader); return am; } private static ColumnMapping ReadColumnMapping(XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Column) { throw Error.UnexpectedElement(XmlMappingConstant.Column, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } ValidateAttributes(reader, new[] { XmlMappingConstant.Name, XmlMappingConstant.DbType, XmlMappingConstant.IsDbGenerated, XmlMappingConstant.IsDiscriminator, XmlMappingConstant.IsPrimaryKey, XmlMappingConstant.IsVersion, XmlMappingConstant.Member, XmlMappingConstant.Storage, XmlMappingConstant.Expression, XmlMappingConstant.CanBeNull, XmlMappingConstant.UpdateCheck, XmlMappingConstant.AutoSync }); ColumnMapping cm = new ColumnMapping(); cm.DbName = OptionalAttribute(reader, XmlMappingConstant.Name); cm.DbType = OptionalAttribute(reader, XmlMappingConstant.DbType); cm.IsDbGenerated = OptionalBoolAttribute(reader, XmlMappingConstant.IsDbGenerated, false); cm.IsDiscriminator = OptionalBoolAttribute(reader, XmlMappingConstant.IsDiscriminator, false); cm.IsPrimaryKey = OptionalBoolAttribute(reader, XmlMappingConstant.IsPrimaryKey, false); cm.IsVersion = OptionalBoolAttribute(reader, XmlMappingConstant.IsVersion, false); cm.MemberName = RequiredAttribute(reader, XmlMappingConstant.Member); cm.StorageMemberName = OptionalAttribute(reader, XmlMappingConstant.Storage); cm.Expression = OptionalAttribute(reader, XmlMappingConstant.Expression); cm.CanBeNull = OptionalNullableBoolAttribute(reader, XmlMappingConstant.CanBeNull); string updateCheck = OptionalAttribute(reader, XmlMappingConstant.UpdateCheck); cm.UpdateCheck = (updateCheck == null) ? UpdateCheck.Always : (UpdateCheck)Enum.Parse(typeof(UpdateCheck), updateCheck); string autoSync = OptionalAttribute(reader, XmlMappingConstant.AutoSync); cm.AutoSync = (autoSync == null) ? AutoSync.Default : (AutoSync)Enum.Parse(typeof(AutoSync), autoSync); AssertEmptyElement(reader); return cm; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. using System; using System.Collections.ObjectModel; using System.Collections.Generic; using System.Linq.Expressions; using System.Linq; using System.Reflection; using System.Runtime.Versioning; using System.Text; using System.Threading; using System.Xml; using System.Xml.Serialization; using LinqToSqlShared.Mapping; namespace System.Data.Linq.Mapping { using System.Data.Linq.Provider; using System.Diagnostics.CodeAnalysis; /// /// Represents a source for mapping information. /// public abstract class MappingSource { MetaModel primaryModel; ReaderWriterLock rwlock; DictionarysecondaryModels; /// /// Gets the MetaModel representing a DataContext and all it's /// accessible tables, functions and entities. /// public MetaModel GetModel(Type dataContextType) { if (dataContextType == null) { throw Error.ArgumentNull("dataContextType"); } MetaModel model = null; if (this.primaryModel == null) { model = this.CreateModel(dataContextType); Interlocked.CompareExchange(ref this.primaryModel, model, null); } // if the primary one matches, use it! if (this.primaryModel.ContextType == dataContextType) { return this.primaryModel; } // the rest of this only happens if you are using the mapping source for // more than one context type // build a map if one is not already defined if (this.secondaryModels == null) { Interlocked.CompareExchange >(ref this.secondaryModels, new Dictionary (), null); } // if we haven't created a read/writer lock, make one now if (this.rwlock == null) { Interlocked.CompareExchange (ref this.rwlock, new ReaderWriterLock(), null); } // lock the map and look inside MetaModel foundModel; this.rwlock.AcquireReaderLock(Timeout.Infinite); try { if (this.secondaryModels.TryGetValue(dataContextType, out foundModel)) { return foundModel; } } finally { this.rwlock.ReleaseReaderLock(); } // if it wasn't found, lock for write and try again this.rwlock.AcquireWriterLock(Timeout.Infinite); try { if (this.secondaryModels.TryGetValue(dataContextType, out foundModel)) { return foundModel; } if (model == null) { model = this.CreateModel(dataContextType); } this.secondaryModels.Add(dataContextType, model); } finally { this.rwlock.ReleaseWriterLock(); } return model; } /// /// Creates a new instance of a MetaModel. This method is called by GetModel(). /// Override this method when defining a new type of MappingSource. /// /// ///protected abstract MetaModel CreateModel(Type dataContextType); } /// /// A mapping source that uses attributes on the context to create the mapping model. /// public sealed class AttributeMappingSource : MappingSource { public AttributeMappingSource() { } protected override MetaModel CreateModel(Type dataContextType) { if (dataContextType == null) { throw Error.ArgumentNull("dataContextType"); } return new AttributedMetaModel(this, dataContextType); } } ////// A mapping source that uses an external XML mapping source to create the model. /// public sealed class XmlMappingSource : MappingSource { DatabaseMapping map; [ResourceExposure(ResourceScope.Assembly)] // map parameter contains type names. private XmlMappingSource(DatabaseMapping map) { this.map = map; } [ResourceExposure(ResourceScope.None)] // Exposure is via map instance variable. [ResourceConsumption(ResourceScope.Assembly | ResourceScope.Machine, ResourceScope.Assembly | ResourceScope.Machine)] // For MappedMetaModel constructor call. protected override MetaModel CreateModel(Type dataContextType) { if (dataContextType == null) { throw Error.ArgumentNull("dataContextType"); } return new MappedMetaModel(this, dataContextType, this.map); } ////// Create a mapping source from xml string. /// /// The type of DataContext to base the mapping on. /// A string containing XML. ///The mapping source. [ResourceExposure(ResourceScope.Assembly)] // Xml contains type names. [ResourceConsumption(ResourceScope.Assembly)] // For FromReader method call. public static XmlMappingSource FromXml(string xml) { if (xml == null) { throw Error.ArgumentNull("xml"); } XmlReader reader = new XmlTextReader(new System.IO.StringReader(xml)); return FromReader(reader); } ////// Create a mapping source from xml reader. /// /// The type of DataContext to base the mapping on. /// An xml reader. ///The mapping source. [ResourceExposure(ResourceScope.Assembly)] // reader parameter contains type names. [ResourceConsumption(ResourceScope.Assembly)] // XmlMappingSource constructor call. public static XmlMappingSource FromReader(XmlReader reader) { if (reader == null) { throw Error.ArgumentNull("reader"); } reader.MoveToContent(); DatabaseMapping db = XmlMappingReader.ReadDatabaseMapping(reader); if (db == null) { throw Error.DatabaseNodeNotFound(XmlMappingConstant.MappingNamespace); } return new XmlMappingSource(db); } ////// Create a mapping source from xml in a stream. /// /// The type of DataContext to base the mapping on. /// A stream of xml. ///The mapping source. [ResourceExposure(ResourceScope.Assembly)] // Stream contains type names. [ResourceConsumption(ResourceScope.Assembly)] // For FromReader method call. public static XmlMappingSource FromStream(System.IO.Stream stream) { if (stream == null) { throw Error.ArgumentNull("stream"); } XmlReader reader = new XmlTextReader(stream); return FromReader(reader); } ////// Create a mapping source from xml loaded from a url. /// /// The type of DataContext to base the mapping on. /// The Url pointing to the xml. ///The mapping source. [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#", Justification="Unknown reason.")] [ResourceExposure(ResourceScope.Machine | ResourceScope.Assembly)] // url parameter which may contain type names. [ResourceConsumption(ResourceScope.Machine | ResourceScope.Assembly)] // XmlTextReader constructor & FromReader method call. public static XmlMappingSource FromUrl(string url) { if (url == null) { throw Error.ArgumentNull("url"); } XmlReader reader = new XmlTextReader(url); try { return FromReader(reader); } finally { reader.Close(); } } } class XmlMappingReader { private static string RequiredAttribute(XmlReader reader, string attribute) { string result = OptionalAttribute(reader, attribute); if (result == null) { throw Error.CouldNotFindRequiredAttribute(attribute, reader.ReadOuterXml()); } return result; } private static string OptionalAttribute(XmlReader reader, string attribute) { return reader.GetAttribute(attribute); } private static bool OptionalBoolAttribute(XmlReader reader, string attribute, bool @default) { string value = OptionalAttribute(reader, attribute); return (value != null) ? bool.Parse(value) : @default; } private static bool? OptionalNullableBoolAttribute(XmlReader reader, string attribute) { string value = OptionalAttribute(reader, attribute); return (value != null) ? (bool?)bool.Parse(value) : null; } private static void AssertEmptyElement(XmlReader reader) { if (!reader.IsEmptyElement) { string nodeName = reader.Name; reader.Read(); if (reader.NodeType != XmlNodeType.EndElement) { throw Error.ExpectedEmptyElement(nodeName, reader.NodeType, reader.Name); } } reader.Skip(); } internal static DatabaseMapping ReadDatabaseMapping(XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Database) { return null; } ValidateAttributes(reader, new[] { XmlMappingConstant.Name, XmlMappingConstant.Provider }); DatabaseMapping dm = new DatabaseMapping(); dm.DatabaseName = RequiredAttribute(reader, XmlMappingConstant.Name); dm.Provider = OptionalAttribute(reader, XmlMappingConstant.Provider); if (!reader.IsEmptyElement) { reader.ReadStartElement(); reader.MoveToContent(); while (reader.NodeType != XmlNodeType.EndElement) { if (reader.NodeType == XmlNodeType.Whitespace || !IsInNamespace(reader)) { reader.Skip(); continue; } switch (reader.LocalName) { case XmlMappingConstant.Table: dm.Tables.Add(ReadTableMapping(reader)); break; case XmlMappingConstant.Function: dm.Functions.Add(ReadFunctionMapping(reader)); break; default: throw Error.UnrecognizedElement(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } reader.MoveToContent(); } if (reader.LocalName != XmlMappingConstant.Database) { throw Error.UnexpectedElement(XmlMappingConstant.Database, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } reader.ReadEndElement(); } else { System.Diagnostics.Debug.Assert(false, "DatabaseMapping has no content"); reader.Skip(); } return dm; } internal static bool IsInNamespace(XmlReader reader) { return reader.LookupNamespace(reader.Prefix) == XmlMappingConstant.MappingNamespace; } internal static void ValidateAttributes(XmlReader reader, string[] validAttributes) { if (reader.HasAttributes) { ListattrList = new List (validAttributes); const string xmlns = "xmlns"; for (int i = 0; i < reader.AttributeCount; i++) { reader.MoveToAttribute(i); // if the node's in the namespace, it is required to be one of the valid ones if (IsInNamespace(reader) && reader.LocalName != xmlns && !attrList.Contains(reader.LocalName)) { throw Error.UnrecognizedAttribute(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : ":", reader.LocalName)); } } reader.MoveToElement(); // Moves the reader back to the element node. } } internal static FunctionMapping ReadFunctionMapping(XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Function) { throw Error.UnexpectedElement(XmlMappingConstant.Function, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } ValidateAttributes(reader, new[] { XmlMappingConstant.Name, XmlMappingConstant.Method, XmlMappingConstant.IsComposable }); FunctionMapping fm = new FunctionMapping(); fm.MethodName = RequiredAttribute(reader, XmlMappingConstant.Method); fm.Name = OptionalAttribute(reader, XmlMappingConstant.Name); fm.IsComposable = OptionalBoolAttribute(reader, XmlMappingConstant.IsComposable, false); if (!reader.IsEmptyElement) { reader.ReadStartElement(); reader.MoveToContent(); while (reader.NodeType != XmlNodeType.EndElement) { if (reader.NodeType == XmlNodeType.Whitespace || !IsInNamespace(reader)) { reader.Skip(); continue; } switch (reader.LocalName) { case XmlMappingConstant.Parameter: fm.Parameters.Add(ReadParameterMapping(reader)); break; case XmlMappingConstant.ElementType: fm.Types.Add(ReadElementTypeMapping(null, reader)); break; case XmlMappingConstant.Return: fm.FunReturn = ReadReturnMapping(reader); break; default: throw Error.UnrecognizedElement(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } reader.MoveToContent(); } reader.ReadEndElement(); } else { // no content is okay reader.Skip(); } return fm; } private static ReturnMapping ReadReturnMapping(XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Return) { throw Error.UnexpectedElement(XmlMappingConstant.Return, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } ValidateAttributes(reader, new[] { XmlMappingConstant.DbType }); ReturnMapping rm = new ReturnMapping(); rm.DbType = OptionalAttribute(reader, XmlMappingConstant.DbType); AssertEmptyElement(reader); return rm; } private static ParameterMapping ReadParameterMapping(XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Parameter) { throw Error.UnexpectedElement(XmlMappingConstant.Parameter, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } ValidateAttributes(reader, new[] { XmlMappingConstant.Name, XmlMappingConstant.DbType, XmlMappingConstant.Parameter, XmlMappingConstant.Direction }); ParameterMapping pm = new ParameterMapping(); pm.Name = RequiredAttribute(reader, XmlMappingConstant.Name); pm.ParameterName = RequiredAttribute(reader, XmlMappingConstant.Parameter); pm.DbType = OptionalAttribute(reader, XmlMappingConstant.DbType); pm.XmlDirection = OptionalAttribute(reader, XmlMappingConstant.Direction); AssertEmptyElement(reader); return pm; } private static TableMapping ReadTableMapping(XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Table) { throw Error.UnexpectedElement(XmlMappingConstant.Table, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } ValidateAttributes(reader, new[] { XmlMappingConstant.Name, XmlMappingConstant.Member }); TableMapping tm = new TableMapping(); tm.TableName = OptionalAttribute(reader, XmlMappingConstant.Name); tm.Member = OptionalAttribute(reader, XmlMappingConstant.Member); if (!reader.IsEmptyElement) { reader.ReadStartElement(); reader.MoveToContent(); while (reader.NodeType != XmlNodeType.EndElement) { if (reader.NodeType == XmlNodeType.Whitespace || !IsInNamespace(reader)) { reader.Skip(); continue; } switch (reader.LocalName) { case XmlMappingConstant.Type: if (tm.RowType != null) { goto default; } tm.RowType = ReadTypeMapping(null, reader); break; default: throw Error.UnrecognizedElement(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } reader.MoveToContent(); } if (reader.LocalName != XmlMappingConstant.Table) { throw Error.UnexpectedElement(XmlMappingConstant.Table, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } reader.ReadEndElement(); } else { System.Diagnostics.Debug.Assert(false, "Table has no content"); reader.Skip(); } return tm; } private static TypeMapping ReadElementTypeMapping(TypeMapping baseType, XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.ElementType) { throw Error.UnexpectedElement(XmlMappingConstant.Type, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } return ReadTypeMappingImpl(baseType, reader); } private static TypeMapping ReadTypeMapping(TypeMapping baseType, XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Type) { throw Error.UnexpectedElement(XmlMappingConstant.Type, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } return ReadTypeMappingImpl(baseType, reader); } private static TypeMapping ReadTypeMappingImpl(TypeMapping baseType, XmlReader reader) { ValidateAttributes(reader, new[] { XmlMappingConstant.Name, XmlMappingConstant.InheritanceCode, XmlMappingConstant.IsInheritanceDefault }); TypeMapping tm = new TypeMapping(); tm.BaseType = baseType; tm.Name = RequiredAttribute(reader, XmlMappingConstant.Name); tm.InheritanceCode = OptionalAttribute(reader, XmlMappingConstant.InheritanceCode); tm.IsInheritanceDefault = OptionalBoolAttribute(reader, XmlMappingConstant.IsInheritanceDefault, false); if (!reader.IsEmptyElement) { reader.ReadStartElement(); reader.MoveToContent(); while (reader.NodeType != XmlNodeType.EndElement) { if (reader.NodeType == XmlNodeType.Whitespace || !IsInNamespace(reader)) { reader.Skip(); continue; } switch (reader.LocalName) { case XmlMappingConstant.Type: tm.DerivedTypes.Add(ReadTypeMapping(tm, reader)); break; case XmlMappingConstant.Association: tm.Members.Add(ReadAssociationMapping(reader)); break; case XmlMappingConstant.Column: tm.Members.Add(ReadColumnMapping(reader)); break; default: throw Error.UnrecognizedElement(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } reader.MoveToContent(); } reader.ReadEndElement(); } else { // no content is okay reader.Skip(); } return tm; } private static AssociationMapping ReadAssociationMapping(XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Association) { throw Error.UnexpectedElement(XmlMappingConstant.Association, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } ValidateAttributes(reader, new[] { XmlMappingConstant.Name, XmlMappingConstant.IsForeignKey, XmlMappingConstant.IsUnique, XmlMappingConstant.Member, XmlMappingConstant.OtherKey, XmlMappingConstant.Storage, XmlMappingConstant.ThisKey, XmlMappingConstant.DeleteRule, XmlMappingConstant.DeleteOnNull, }); AssociationMapping am = new AssociationMapping(); am.DbName = OptionalAttribute(reader, XmlMappingConstant.Name); am.IsForeignKey = OptionalBoolAttribute(reader, XmlMappingConstant.IsForeignKey, false); am.IsUnique = OptionalBoolAttribute(reader, XmlMappingConstant.IsUnique, false); am.MemberName = RequiredAttribute(reader, XmlMappingConstant.Member); am.OtherKey = OptionalAttribute(reader, XmlMappingConstant.OtherKey); am.StorageMemberName = OptionalAttribute(reader, XmlMappingConstant.Storage); am.ThisKey = OptionalAttribute(reader, XmlMappingConstant.ThisKey); am.DeleteRule = OptionalAttribute(reader, XmlMappingConstant.DeleteRule); am.DeleteOnNull = OptionalBoolAttribute(reader, XmlMappingConstant.DeleteOnNull, false); AssertEmptyElement(reader); return am; } private static ColumnMapping ReadColumnMapping(XmlReader reader) { System.Diagnostics.Debug.Assert(reader.NodeType == XmlNodeType.Element); if (!IsInNamespace(reader) || reader.LocalName != XmlMappingConstant.Column) { throw Error.UnexpectedElement(XmlMappingConstant.Column, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}{2}", reader.Prefix, String.IsNullOrEmpty(reader.Prefix) ? "" : "/", reader.LocalName)); } ValidateAttributes(reader, new[] { XmlMappingConstant.Name, XmlMappingConstant.DbType, XmlMappingConstant.IsDbGenerated, XmlMappingConstant.IsDiscriminator, XmlMappingConstant.IsPrimaryKey, XmlMappingConstant.IsVersion, XmlMappingConstant.Member, XmlMappingConstant.Storage, XmlMappingConstant.Expression, XmlMappingConstant.CanBeNull, XmlMappingConstant.UpdateCheck, XmlMappingConstant.AutoSync }); ColumnMapping cm = new ColumnMapping(); cm.DbName = OptionalAttribute(reader, XmlMappingConstant.Name); cm.DbType = OptionalAttribute(reader, XmlMappingConstant.DbType); cm.IsDbGenerated = OptionalBoolAttribute(reader, XmlMappingConstant.IsDbGenerated, false); cm.IsDiscriminator = OptionalBoolAttribute(reader, XmlMappingConstant.IsDiscriminator, false); cm.IsPrimaryKey = OptionalBoolAttribute(reader, XmlMappingConstant.IsPrimaryKey, false); cm.IsVersion = OptionalBoolAttribute(reader, XmlMappingConstant.IsVersion, false); cm.MemberName = RequiredAttribute(reader, XmlMappingConstant.Member); cm.StorageMemberName = OptionalAttribute(reader, XmlMappingConstant.Storage); cm.Expression = OptionalAttribute(reader, XmlMappingConstant.Expression); cm.CanBeNull = OptionalNullableBoolAttribute(reader, XmlMappingConstant.CanBeNull); string updateCheck = OptionalAttribute(reader, XmlMappingConstant.UpdateCheck); cm.UpdateCheck = (updateCheck == null) ? UpdateCheck.Always : (UpdateCheck)Enum.Parse(typeof(UpdateCheck), updateCheck); string autoSync = OptionalAttribute(reader, XmlMappingConstant.AutoSync); cm.AutoSync = (autoSync == null) ? AutoSync.Default : (AutoSync)Enum.Parse(typeof(AutoSync), autoSync); AssertEmptyElement(reader); return cm; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ImageDrawing.cs
- CustomPeerResolverService.cs
- TemplatedWizardStep.cs
- DrawListViewSubItemEventArgs.cs
- DateTimeUtil.cs
- GridErrorDlg.cs
- ListDesigner.cs
- TranslateTransform3D.cs
- PropertyPathConverter.cs
- PropertyMetadata.cs
- PolicyLevel.cs
- sqlstateclientmanager.cs
- InputLangChangeRequestEvent.cs
- FontStretch.cs
- UrlPath.cs
- ScriptingSectionGroup.cs
- MetadataItem_Static.cs
- LeaseManager.cs
- ToolStripDropDownButton.cs
- PropertyFilter.cs
- XmlNodeChangedEventArgs.cs
- OleServicesContext.cs
- NativeCppClassAttribute.cs
- ActivityDesignerResources.cs
- CookieProtection.cs
- TaskFormBase.cs
- ManifestResourceInfo.cs
- SiteMapHierarchicalDataSourceView.cs
- WhitespaceRule.cs
- Helpers.cs
- InputScopeAttribute.cs
- Collection.cs
- CachedFontFamily.cs
- PropertyStore.cs
- InstanceLockLostException.cs
- MsmqTransportSecurity.cs
- TrustSection.cs
- XmlQualifiedNameTest.cs
- DesignerActionUIStateChangeEventArgs.cs
- PrintPreviewControl.cs
- XmlValidatingReaderImpl.cs
- FacetChecker.cs
- CopyAttributesAction.cs
- cookiecollection.cs
- SqlPersonalizationProvider.cs
- CustomCategoryAttribute.cs
- UriSection.cs
- DefaultObjectMappingItemCollection.cs
- InputReportEventArgs.cs
- NativeCompoundFileAPIs.cs
- XMLDiffLoader.cs
- MatrixTransform.cs
- MetafileHeaderWmf.cs
- WindowsFont.cs
- InternalControlCollection.cs
- Menu.cs
- CustomValidator.cs
- WebServiceMethodData.cs
- FormView.cs
- ItemList.cs
- TimeSpanStorage.cs
- IProvider.cs
- GridItemPattern.cs
- MemoryResponseElement.cs
- WebHostScriptMappingsInstallComponent.cs
- BamlRecordWriter.cs
- TabControlCancelEvent.cs
- DbConnectionOptions.cs
- IntSecurity.cs
- DbResourceAllocator.cs
- EnumType.cs
- StrokeFIndices.cs
- MetafileHeaderWmf.cs
- PenThreadWorker.cs
- Point3DIndependentAnimationStorage.cs
- List.cs
- ProfileSettingsCollection.cs
- XmlAutoDetectWriter.cs
- ContextMarshalException.cs
- XsltLoader.cs
- UInt32.cs
- TypeGeneratedEventArgs.cs
- TextDecoration.cs
- KnownBoxes.cs
- PersistChildrenAttribute.cs
- dbenumerator.cs
- WebBrowserBase.cs
- Constants.cs
- PipelineModuleStepContainer.cs
- EnumDataContract.cs
- ResourceManager.cs
- StylusPointPropertyId.cs
- PlatformCulture.cs
- LogStore.cs
- ProxyBuilder.cs
- AssemblyBuilder.cs
- DataGridViewCellValueEventArgs.cs
- DataListCommandEventArgs.cs
- SafeSystemMetrics.cs
- AttachedPropertyBrowsableForTypeAttribute.cs