using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Security.Permissions;
using System.Web.DynamicData.ModelProviders;
using System.Linq;
using System.Web.UI;
namespace System.Web.DynamicData {
///
/// A special column representing many-1 relationships
///
public class MetaForeignKeyColumn : MetaColumn, IMetaForeignKeyColumn {
// Maps a foreign key name to the name that should be used in a Linq expression for filtering
// i.e. the foreignkey name might be surfaced through a custom type descriptor e.g. CategoryID but we might really want to use
// Category.CategoryId in the expression
private Dictionary _foreignKeyFilterMapping;
public MetaForeignKeyColumn(MetaTable table, ColumnProvider entityMember)
: base(table, entityMember) {
}
///
/// Perform initialization logic for this column
///
internal protected override void Initialize() {
base.Initialize();
ParentTable = Model.GetTable(Provider.Association.ToTable.Name, Table.DataContextType);
CreateForeignKeyFilterMapping(ForeignKeyNames, ParentTable.PrimaryKeyNames, (foreignKey) => Table.EntityType.GetProperty(foreignKey) != null);
}
internal void CreateForeignKeyFilterMapping(IList foreignKeyNames, IList primaryKeyNames, Func propertyExists) {
// HACK: Some tests don't mock foreign key names, but this should never be the case at runtime
if (foreignKeyNames == null) {
return;
}
int pKIndex = 0;
foreach (string fkName in foreignKeyNames) {
if (!propertyExists(fkName)) {
if (_foreignKeyFilterMapping == null) {
_foreignKeyFilterMapping = new Dictionary();
}
_foreignKeyFilterMapping[fkName] = Name + "." + primaryKeyNames[pKIndex];
}
pKIndex++;
}
}
///
/// The parent table of the relationship (e.g. Categories in Products->Categories)
///
public MetaTable ParentTable {
get;
// internal for unit testing
internal set;
}
///
/// Returns true if this foriegn key column is part of the primary key of its table
/// e.g. Order and Product are PKs in the Order_Details table
///
public bool IsPrimaryKeyInThisTable {
get {
return Provider.Association.IsPrimaryKeyInThisTable;
}
}
///
/// This is used when saving the value of a foreign key, e.g. when selected from a drop down.
///
public void ExtractForeignKey(IDictionary dictionary, string value) {
if (String.IsNullOrEmpty(value)) {
// If the value is null, set all the FKs to null
foreach (string fkName in ForeignKeyNames) {
dictionary[fkName] = null;
}
}
else {
string[] fkValues = Misc.ParseCommaSeparatedString(value);
Debug.Assert(fkValues.Length == ForeignKeyNames.Count);
for (int i = 0; i < fkValues.Length; i++) {
dictionary[ForeignKeyNames[i]] = fkValues[i];
}
}
}
///
/// Return the value of all the foreign keys components for the passed in row
///
public IList