File: DynamicData\ModelProviders\DLinqAssociationProvider.cs
Project: ndp\fx\src\xsp\system\DynamicData\System.Web.DynamicData.csproj (System.Web.DynamicData)
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Linq.Mapping;
using System.Linq;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Specialized;
using System.Collections;
using System.Globalization;
 
namespace System.Web.DynamicData.ModelProviders {
    internal sealed class DLinqAssociationProvider : AssociationProvider {
 
        public DLinqAssociationProvider(DLinqColumnProvider column) {
            FromColumn = column;
 
            MetaAssociation association = column.Member.Association;
 
            SetOtherEndOfAssociation(association);
 
            SetDirection(association);
            Debug.Assert(Direction != AssociationDirection.ManyToMany, "Many to Many is not supported by Linq to SQL");
 
            SetAssociationKeyInfo(association);
        }
 
        private void SetAssociationKeyInfo(MetaAssociation association) {
            DLinqColumnProvider column = (DLinqColumnProvider)FromColumn;
 
            List<string> foreignKeyNames = new List<string>();
 
            int count = column.Member.Association.ThisKey.Count;
            for (int i = 0; i < count; i++) {
                MetaDataMember thisKeyMetaDataMember = column.Member.Association.ThisKey[i];
                MetaDataMember otherKeyMetaDataMember = column.Member.Association.OtherKey[i];
 
                DLinqColumnProvider thisEntityMemberComponent = FindColumn(column.Table, thisKeyMetaDataMember.Name);
 
                if (ShouldRemoveThisAssociation(association)) {
                    column.ShouldRemove = true;
                    return;
                }
 
                foreignKeyNames.Add(thisEntityMemberComponent.Name);
 
                if (thisEntityMemberComponent.IsPrimaryKey) {
                    IsPrimaryKeyInThisTable = true;
                }
                if (association.IsForeignKey) {
                    thisEntityMemberComponent.IsForeignKeyComponent = true;
                }
            }
 
            ForeignKeyNames = new ReadOnlyCollection<string>(foreignKeyNames);
        }
 
        private bool ShouldRemoveThisAssociation(MetaAssociation association) {
            if (Direction == AssociationDirection.ManyToOne && !association.OtherKeyIsPrimaryKey) {
                return true;
            }
            if (Direction == AssociationDirection.OneToMany && !association.ThisKeyIsPrimaryKey) {
                return true;
            }
            if (Direction == AssociationDirection.OneToOne) {
                if (!association.IsForeignKey && !association.ThisKeyIsPrimaryKey) {
                    return true;
                }
                if (association.IsForeignKey && !association.OtherKeyIsPrimaryKey) {
                    return true;
                }
            }
 
            return false;
        }
 
        private void SetOtherEndOfAssociation(MetaAssociation association) {
            DLinqTableProvider entityMemberParentEntity = (DLinqTableProvider)FromColumn.Table;
            DLinqDataModelProvider parentEntityDataContext = (DLinqDataModelProvider)entityMemberParentEntity.DataModel;
            if (association.OtherMember != null) {
                ToColumn = parentEntityDataContext.ColumnLookup[(PropertyInfo)association.OtherMember.Member];
            } else {
                ToTable = ((DLinqDataModelProvider)FromColumn.Table.DataModel).DLinqTables.Single(tp => tp.EntityType == association.OtherType.Type);
            }
        }
 
        private static DLinqColumnProvider FindColumn(TableProvider table, String columnName) {
            // 
            return (DLinqColumnProvider)table.Columns.First(member => member.Name.Equals(columnName));
        }
 
        private void SetDirection(MetaAssociation association) {
            if (association.IsMany) {
                Direction = AssociationDirection.OneToMany;
            } else if (association.OtherMember == null || association.OtherMember.Association.IsMany) {
                // there might not be the other member if this is a one-sided association
                Direction = AssociationDirection.ManyToOne;
            } else {
                Direction = AssociationDirection.OneToOne;
            }
        }
 
        public override string GetSortExpression(ColumnProvider sortColumn) {
            return GetSortExpression(sortColumn, "{0}.{1}");
        }
    }
}