File: DynamicData\ModelProviders\AssociationProvider.cs
Project: ndp\fx\src\xsp\system\DynamicData\System.Web.DynamicData.csproj (System.Web.DynamicData)
using System.Collections.ObjectModel;
using System.Globalization;
using System.Web.Resources;
 
namespace System.Web.DynamicData.ModelProviders {
    /// <summary>
    /// Specifies the association cardinality
    /// </summary>
    public enum AssociationDirection {
        /// <summary>
        /// 1-1
        /// </summary>
        OneToOne,
        /// <summary>
        /// one to many
        /// </summary>
        OneToMany,
        /// <summary>
        /// many to one
        /// </summary>
        ManyToOne,
        /// <summary>
        /// many to many
        /// </summary>
        ManyToMany
    }
 
    /// <summary>
    /// Base provider class for associations between columns
    /// Each provider type (e.g. Linq To Sql, Entity Framework, 3rd party) extends this class.
    /// </summary>
    public abstract class AssociationProvider {
        private TableProvider _toTable;
 
        /// <summary>
        /// The type of association
        /// </summary>
        public virtual AssociationDirection Direction { get; protected set; }
 
        /// <summary>
        /// The source column of the association
        /// </summary>
        public virtual ColumnProvider FromColumn { get; protected set; }
 
        /// <summary>
        /// The destination table of the association
        /// </summary>
        public virtual TableProvider ToTable {
            get {
                if (_toTable != null) {
                    return _toTable;
                }
 
                if (ToColumn != null) {
                    return ToColumn.Table;
                }
 
                return null;
            }
            protected set {
                _toTable = value;
            }
        }
 
        /// <summary>
        /// The destination column of the association
        /// </summary>
        public virtual ColumnProvider ToColumn { get; protected set; }
 
        /// <summary>
        /// Returns true if the From Column part of the primary key of its table
        /// e.g. Order and Product are PKs in the Order_Details table
        /// </summary>
        public virtual bool IsPrimaryKeyInThisTable { get; protected set; }
 
        /// <summary>
        /// The names of the underlying foreign keys that make up this association
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification="It's a readonly collection, so the warning is incorrect")]
        public virtual ReadOnlyCollection<string> ForeignKeyNames { get; protected set; }
 
        /// <summary>
        /// Returns a string representing the sort expression that would be used for
        /// sorting the column represented by this association. The parameter is the
        /// property of the strongly typed entity used as the sort key for that entity.
        /// For example, assume that this association represents the Category column
        /// in the Products table. The sortColumn paramater is "CategoryName",
        /// meaning that this method is being asked to return the sort expression for
        /// sorting the Category column by the CategoryName property of the Category entity.
        /// The result sort expression would be "Category.CategoryName".
        /// The result of this method should be affected by whether the underlying data
        /// model is capable of sorting the entity by the given sort column (see
        /// ColumnProvider.IsSortable). The method can return a null value to indicate
        /// that sorting is not supported.
        /// </summary>
        /// <param name="sortColumn">the column to sort the entity by</param>
        /// <returns>the sort expression string, or null if sort is not supported for the
        /// given sort column</returns>
        public virtual string GetSortExpression(ColumnProvider sortColumn) {
            return null;
        }
 
        internal string GetSortExpression(ColumnProvider sortColumn, string format) {
            if (Direction == AssociationDirection.OneToMany || Direction == AssociationDirection.ManyToMany) {
                throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
                    DynamicDataResources.AssociationProvider_DirectionDoesNotSupportSorting,
                    Direction));
            }
 
            if (sortColumn == null) {
                throw new ArgumentNullException("sortColumn");
            }
 
            if (!ToTable.Columns.Contains(sortColumn)) {
                throw new ArgumentException(DynamicDataResources.AssociationProvider_SortColumnDoesNotBelongToEndTable, "sortColumn");
            }
 
            if (sortColumn.IsSortable) {
                return String.Format(CultureInfo.InvariantCulture, format, FromColumn.Name, sortColumn.Name);
            } else {
                return null;
            }
        }
    }
}