using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; using System.Linq; using System.Diagnostics.CodeAnalysis; namespace System.Data.Linq.Mapping { /// /// A MetaModel is an abstraction representing the mapping between a database and domain objects /// public abstract class MetaModel { /// /// The mapping source that originated this model. /// public abstract MappingSource MappingSource { get; } /// /// The type of DataContext type this model describes. /// public abstract Type ContextType { get; } /// /// The name of the database. /// public abstract string DatabaseName { get; } /// /// The CLR type that implements IProvider to use as a provider. /// public abstract Type ProviderType { get; } /// /// Gets the MetaTable associated with a given type. /// /// The CLR row type. /// The MetaTable if one exists, otherwise null. public abstract MetaTable GetTable(Type rowType); /// /// Gets the MetaFunction corresponding to a database function: user-defined function, table-valued function or stored-procedure. /// /// The method defined on the DataContext or subordinate class that represents the database function. /// The MetaFunction if one exists, otherwise null. public abstract MetaFunction GetFunction(MethodInfo method); /// /// Get an enumeration of all tables. /// /// An enumeration of all the MetaTables [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification="Non-trivial operations are not suitable for properties.")] public abstract IEnumerable GetTables(); /// /// Get an enumeration of all functions. /// /// An enumeration of all the MetaFunctions [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification="Non-trivial operations are not suitable for properties.")] public abstract IEnumerable GetFunctions(); /// /// This method discovers the MetaType for the given Type. /// public abstract MetaType GetMetaType(Type type); /// /// Internal value used to determine a reference identity for comparing meta models /// without needing to keep track of the actual meta model reference. /// private object identity = new object(); internal object Identity { get { return this.identity; } } } /// /// A MetaTable represents an abstraction of a database table (or view) /// public abstract class MetaTable { /// /// The MetaModel containing this MetaTable. /// public abstract MetaModel Model { get; } /// /// The name of the table as defined by the database. /// public abstract string TableName { get; } /// /// The MetaType describing the type of the rows of the table. /// public abstract MetaType RowType { get; } /// /// The DataContext method used to perform insert operations /// public abstract MethodInfo InsertMethod { get; } /// /// The DataContext method used to perform update operations /// public abstract MethodInfo UpdateMethod { get; } /// /// The DataContext method used to perform delete operations /// public abstract MethodInfo DeleteMethod { get; } } /// /// A MetaType represents the mapping of a domain object type onto a database table's columns. /// public abstract class MetaType { /// /// The MetaModel containing this MetaType. /// public abstract MetaModel Model { get; } /// /// The MetaTable using this MetaType for row definition. /// public abstract MetaTable Table { get; } /// /// The underlying CLR type. /// [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "The contexts in which this is available are fairly specific.")] public abstract Type Type { get; } /// /// The name of the MetaType (same as the CLR type's name). /// public abstract string Name { get; } /// /// True if the MetaType is an entity type. /// public abstract bool IsEntity { get; } /// /// True if the underlying type can be instantiated as the result of a query. /// public abstract bool CanInstantiate { get; } /// /// The member that represents the auto-generated identity column, or null if there is none. /// public abstract MetaDataMember DBGeneratedIdentityMember { get; } /// /// The member that represents the row-version or timestamp column, or null if there is none. /// public abstract MetaDataMember VersionMember { get; } /// /// The member that represents the inheritance discriminator column, or null if there is none. /// public abstract MetaDataMember Discriminator { get; } /// /// True if the type has any persistent member with an UpdateCheck policy other than Never. /// public abstract bool HasUpdateCheck { get; } /// /// True if the type is part of a mapped inheritance hierarchy. /// public abstract bool HasInheritance { get; } /// /// True if this type defines an inheritance code. /// public abstract bool HasInheritanceCode { get; } /// /// The inheritance code defined by this type. /// public abstract object InheritanceCode { get; } /// /// True if this type is used as the default of an inheritance hierarchy. /// public abstract bool IsInheritanceDefault { get; } /// /// The root type of the inheritance hierarchy. /// public abstract MetaType InheritanceRoot { get; } /// /// The base metatype in the inheritance hierarchy. /// public abstract MetaType InheritanceBase { get; } /// /// The type that is the default of the inheritance hierarchy. /// public abstract MetaType InheritanceDefault { get; } /// /// Gets the MetaType for an inheritance sub type. /// /// The root or sub type of the inheritance hierarchy. /// The MetaType. public abstract MetaType GetInheritanceType(Type type); /// /// Gets type associated with the specified inheritance code. /// /// The inheritance code /// The MetaType. public abstract MetaType GetTypeForInheritanceCode(object code); /// /// Gets an enumeration of all types defined by an inheritance hierarchy. /// /// Enumeration of MetaTypes. public abstract ReadOnlyCollection InheritanceTypes { get; } /// /// Returns true if the MetaType or any base MetaType has an OnLoaded method. /// public abstract bool HasAnyLoadMethod { get; } /// /// Returns true if the MetaType or any base MetaType has an OnValidate method. /// public abstract bool HasAnyValidateMethod { get; } /// /// Gets an enumeration of the immediate derived types in an inheritance hierarchy. /// /// Enumeration of MetaTypes. public abstract ReadOnlyCollection DerivedTypes { get; } /// /// Gets an enumeration of all the data members (fields and properties). /// public abstract ReadOnlyCollection DataMembers { get; } /// /// Gets an enumeration of all the persistent data members (fields and properties mapped into database columns). /// public abstract ReadOnlyCollection PersistentDataMembers { get; } /// /// Gets an enumeration of all the data members that define up the unique identity of the type. /// public abstract ReadOnlyCollection IdentityMembers { get; } /// /// Gets an enumeration of all the associations. /// public abstract ReadOnlyCollection Associations { get; } /// /// Gets the MetaDataMember associated with the specified member. /// /// The CLR member. /// The MetaDataMember if there is one, otherwise null. public abstract MetaDataMember GetDataMember(MemberInfo member); /// /// The method called when the entity is first loaded. /// public abstract MethodInfo OnLoadedMethod { get; } /// /// The method called to ensure the entity is in a valid state. /// public abstract MethodInfo OnValidateMethod { get; } } /// /// A MetaDataMember represents the mapping between a domain object's field or property into a database table's column. /// [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "MetaData", Justification = "The capitalization was deliberately chosen.")] public abstract class MetaDataMember { /// /// The MetaType containing this data member. /// public abstract MetaType DeclaringType { get; } /// /// The underlying MemberInfo. /// public abstract MemberInfo Member { get; } /// /// The member that actually stores this member's data. /// public abstract MemberInfo StorageMember { get; } /// /// The name of the member, same as the MemberInfo name. /// public abstract string Name { get; } /// /// The name of the column (or constraint) in the database. /// public abstract string MappedName { get; } /// /// The oridinal position of this member in the default layout of query results. /// public abstract int Ordinal { get; } /// /// The type of this member. /// [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "The contexts in which this is available are fairly specific.")] public abstract Type Type { get; } /// /// True if this member is declared by the specified type. /// /// Type to check. public abstract bool IsDeclaredBy(MetaType type); /// /// The accessor used to get/set the value of this member. /// public abstract MetaAccessor MemberAccessor { get; } /// /// The accessor used to get/set the storage value of this member. /// public abstract MetaAccessor StorageAccessor { get; } /// /// The accessor used to get/set the deferred value of this member (without causing fetch). /// public abstract MetaAccessor DeferredValueAccessor { get; } /// /// The accessor used to get/set the deferred source of this member. /// public abstract MetaAccessor DeferredSourceAccessor { get; } /// /// True if this member is defer-loaded by default. /// public abstract bool IsDeferred { get; } /// /// True if this member is mapped to a column (or constraint). /// public abstract bool IsPersistent { get; } /// /// True if this member defines an association relationship. /// public abstract bool IsAssociation { get; } /// /// True if this member is part of the type's identity. /// public abstract bool IsPrimaryKey { get; } /// /// True if this member is automatically generated by the database. /// [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db", Justification = "Conforms to legacy spelling.")] public abstract bool IsDbGenerated { get; } /// /// True if this member represents the row version or timestamp. /// public abstract bool IsVersion { get; } /// /// True if this member represents the inheritance discriminator. /// public abstract bool IsDiscriminator { get; } /// /// True if this member's value can be assigned the null value. /// public abstract bool CanBeNull { get; } /// /// The type of the database column. /// [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db", Justification = "Conforms to legacy spelling.")] public abstract string DbType { get; } /// /// Expression defining a computed column. /// public abstract string Expression { get; } /// /// The optimistic concurrency check policy for this member. /// public abstract UpdateCheck UpdateCheck { get; } /// /// Specifies for inserts and updates when this member should be read back after the /// operation completes. /// public abstract AutoSync AutoSync { get; } /// /// The MetaAssociation corresponding to this member, or null if there is none. /// public abstract MetaAssociation Association { get; } /// /// The DataContext method used to perform load operations /// public abstract MethodInfo LoadMethod { get; } } /// /// A MetaFunction represents the mapping between a context method and a database function. /// public abstract class MetaFunction { /// /// The MetaModel containing this function. /// public abstract MetaModel Model { get; } /// /// The underlying context method. /// public abstract MethodInfo Method { get; } /// /// The name of the method (same as the MethodInfo's name). /// public abstract string Name { get; } /// /// The name of the database function or procedure. /// public abstract string MappedName { get; } /// /// True if the function can be composed within a query /// [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Composable", Justification="Spelling is correct.")] public abstract bool IsComposable { get; } /// /// Gets an enumeration of the function parameters. /// /// public abstract ReadOnlyCollection Parameters { get; } /// /// The return parameter /// public abstract MetaParameter ReturnParameter { get; } /// /// True if the stored procedure has multiple result types. /// public abstract bool HasMultipleResults { get; } /// /// An enumeration of all the known result row types of a stored-procedure. /// /// Enumeration of possible result row types. public abstract ReadOnlyCollection ResultRowTypes { get; } } /// /// A MetaParameter represents the mapping between a method parameter and a database function parameter. /// public abstract class MetaParameter { /// /// The underlying method parameter. /// public abstract ParameterInfo Parameter { get; } /// /// The name of the parameter (same as the ParameterInfo's name). /// public abstract string Name { get; } /// /// The name of the database function's parameter. /// public abstract string MappedName { get; } /// /// The CLR type of the parameter. /// public abstract Type ParameterType { get; } /// /// The database type of the parameter. /// [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Db", Justification = "Conforms to legacy spelling.")] public abstract string DbType { get; } } /// /// A MetaAssociation represents an association relationship between two entity types. /// public abstract class MetaAssociation { /// /// The type on the other end of the association. /// public abstract MetaType OtherType { get; } /// /// The member on this side that represents the association. /// public abstract MetaDataMember ThisMember { get; } /// /// The member on the other side of this association that represents the reverse association (may be null). /// public abstract MetaDataMember OtherMember { get; } /// /// A list of members representing the values on this side of the association. /// public abstract ReadOnlyCollection ThisKey { get; } /// /// A list of members representing the values on the other side of the association. /// public abstract ReadOnlyCollection OtherKey { get; } /// /// True if the association is OneToMany. /// public abstract bool IsMany { get; } /// /// True if the other type is the parent of this type. /// public abstract bool IsForeignKey { get; } /// /// True if the association is unique (defines a uniqueness constraint). /// public abstract bool IsUnique { get; } /// /// True if the association may be null (key values). /// public abstract bool IsNullable { get; } /// /// True if the ThisKey forms the identity (primary key) of the this type. /// public abstract bool ThisKeyIsPrimaryKey { get; } /// /// True if the OtherKey forms the identity (primary key) of the other type. /// public abstract bool OtherKeyIsPrimaryKey { get; } /// /// Specifies the behavior when the child is deleted (e.g. CASCADE, SET NULL). /// Returns null if no action is specified on delete. /// public abstract string DeleteRule { get; } /// /// Specifies whether the object should be deleted when this association /// is set to null. /// public abstract bool DeleteOnNull { get; } } /// /// A MetaAccessor /// public abstract class MetaAccessor { /// /// The type of the member accessed by this accessor. /// [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "The contexts in which this is available are fairly specific.")] public abstract Type Type { get; } /// /// Gets the value as an object. /// /// The instance to get the value from. /// Value. public abstract object GetBoxedValue(object instance); /// /// Sets the value as an object. /// /// The instance to set the value into. /// The value to set. [SuppressMessage("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification="[....]: Needs to handle classes and structs.")] [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", Justification="Unknown reason.")] public abstract void SetBoxedValue(ref object instance, object value); /// /// True if the instance has a loaded or assigned value. /// public virtual bool HasValue(object instance) { return true; } /// /// True if the instance has an assigned value. /// public virtual bool HasAssignedValue(object instance) { return true; } /// /// True if the instance has a value loaded from a deferred source. /// public virtual bool HasLoadedValue(object instance) { return false; } } /// /// A strongly-typed MetaAccessor. Used for reading from and writing to /// CLR objects. /// /// The type of the object /// The type of the accessed member public abstract class MetaAccessor : MetaAccessor { /// /// The underlying CLR type. /// public override Type Type { get { return typeof(TMember); } } /// /// Set the boxed value on an instance. /// public override void SetBoxedValue(ref object instance, object value) { TEntity tInst = (TEntity)instance; this.SetValue(ref tInst, (TMember)value); instance = tInst; } /// /// Retrieve the boxed value. /// public override object GetBoxedValue(object instance) { return this.GetValue((TEntity)instance); } /// /// Gets the strongly-typed value. /// public abstract TMember GetValue(TEntity instance); /// /// Sets the strongly-typed value /// [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#", Justification = "Unknown reason.")] public abstract void SetValue(ref TEntity instance, TMember value); } }