1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
using System.Data.Metadata.Edm;
using System.Diagnostics;
using System.Linq;
using System.Globalization;
using System.Reflection;
namespace System.Web.DynamicData.ModelProviders {
internal sealed class EFColumnProvider : ColumnProvider {
private EFTableProvider _table;
private EFAssociationProvider _association;
private bool _isAssociation;
private bool _isSortableProcessed;
private const string StoreGeneratedMetadata = "http://schemas.microsoft.com/ado/2009/02/edm/annotation:StoreGeneratedPattern";
public EFColumnProvider(EntityType entityType, EFTableProvider table, EdmMember m, bool isPrimaryKey)
: base(table) {
EdmMember = m;
IsPrimaryKey = isPrimaryKey;
_table = table;
MaxLength = 0;
Name = EdmMember.Name;
//
IsCustomProperty = false;
//
var property = EdmMember as EdmProperty;
if (property != null) {
IsForeignKeyComponent = DetermineIsForeignKeyComponent(property);
IsGenerated = IsServerGenerated(property);
}
ProcessFacets();
var navProp = m as NavigationProperty;
if (navProp != null) {
_isAssociation = true;
long key = EFAssociationProvider.BuildRelationshipKey(entityType, navProp.FromEndMember);
((EFDataModelProvider)table.DataModel).RelationshipEndLookup[key] = this;
}
}
private bool DetermineIsForeignKeyComponent(EdmProperty property) {
var navigationProperties = property.DeclaringType.Members.OfType<NavigationProperty>();
// Look at all NavigationProperties (i.e. strongly-type relationship columns) of the table this column belong to and
// see if there is a foreign key that matches this property
// If this is a 1 to 0..1 relationship and we are processing the more primary side. i.e in the Student in Student-StudentDetail
// and this is the primary key we don't want to check the relationship type since if there are no constraints we will treat the primary key as a foreign key.
return navigationProperties.Any(n => EFAssociationProvider.GetDependentPropertyNames(n, !IsPrimaryKey /* checkRelationshipType */).Contains(property.Name));
}
private static bool IsServerGenerated(EdmProperty property) {
MetadataProperty generated;
if (property.MetadataProperties.TryGetValue(StoreGeneratedMetadata, false, out generated)) {
return "Identity" == (string)generated.Value || "Computed" == (string)generated.Value;
}
return false;
}
private void ProcessFacets() {
foreach (Facet facet in EdmMember.TypeUsage.Facets) {
switch (facet.Name) {
case "MaxLength":
if (facet.IsUnbounded) {
// If it's marked as unbounded, treat it as max int
MaxLength = Int32.MaxValue;
}
else if (facet.Value != null && facet.Value is int) {
MaxLength = (int)facet.Value;
}
break;
case "Nullable":
Nullable = (bool)facet.Value;
break;
}
}
}
internal EdmMember EdmMember {
get;
private set;
}
#region IEntityMember Members
public override PropertyInfo EntityTypeProperty {
//
get { return _table.EntityType.GetProperty(Name); }
}
public override Type ColumnType {
get {
if (base.ColumnType == null) {
//
var edmType = EdmMember.TypeUsage.EdmType;
if (edmType is EntityType) {
base.ColumnType = ((EFDataModelProvider)this.Table.DataModel).GetClrType(edmType);
}
else if (edmType is CollectionType) {
// get the EdmType that this CollectionType is wrapping
base.ColumnType = ((EFDataModelProvider)this.Table.DataModel).GetClrType(((CollectionType)edmType).TypeUsage.EdmType);
}
else if (edmType is PrimitiveType) {
base.ColumnType = ((PrimitiveType)edmType).ClrEquivalentType;
}
else if (edmType is EnumType) {
base.ColumnType = ((EFDataModelProvider)this.Table.DataModel).GetClrType((EnumType)edmType);
}
else {
Debug.Assert(false, String.Format(CultureInfo.CurrentCulture, "Unknown EdmType {0}.", edmType.GetType().FullName));
}
}
return base.ColumnType;
}
}
public override bool IsSortable {
get {
if (!_isSortableProcessed) {
base.IsSortable = (ColumnType != typeof(byte[]));
_isSortableProcessed = true;
}
return base.IsSortable;
}
}
public override AssociationProvider Association {
get {
if (!_isAssociation) {
return null;
}
if (_association == null) {
_association = new EFAssociationProvider(this, (NavigationProperty)EdmMember);
}
return _association;
}
}
#endregion
internal static bool IsSupportedEdmMemberType(EdmMember member) {
var edmType = member.TypeUsage.EdmType;
return edmType is EntityType || edmType is CollectionType || edmType is PrimitiveType || edmType is EnumType;
}
}
}
|