public EFCodeFirstTableProvider(EFCodeFirstDataModelProvider dataModel, EntitySet entitySet, EntityType entityType, Type entityClrType, Type parentEntityClrType, Type rootEntityClrType, string name) : base(dataModel) { EntityType = entityClrType; Name = name; DataContextPropertyName = entitySet.Name; ParentEntityType = parentEntityClrType; RootEntityType = rootEntityClrType; var genericMethod = typeof(ObjectContext).GetMethod("CreateQuery"); CreateQueryMethod = genericMethod.MakeGenericMethod(EntityType); CreateQueryString = CreateEntitySqlQueryString(entitySet); var keyMembers = entityType.KeyMembers; // columns (entity properties) // note 1: keys are also available through es.ElementType.KeyMembers // note 2: this includes "nav properties", kind of fancy, two-way relationship objects var columns = new List<ColumnProvider>(); foreach (EdmMember m in entityType.Members) { if (EFCodeFirstColumnProvider.IsSupportedEdmMemberType(m) && IsPublicProperty(entityClrType, m.Name)) { EFCodeFirstColumnProvider entityMember = new EFCodeFirstColumnProvider(entityType, this, m, keyMembers.Contains(m)); columns.Add(entityMember); } } _roColumns = new ReadOnlyCollection<ColumnProvider>(columns); }
public EFCodeFirstAssociationProvider(EFCodeFirstColumnProvider column, NavigationProperty navigationProperty) { FromColumn = column; var entityMemberParentEntity = (EFCodeFirstTableProvider)column.Table; var parentEntityModel = (EFCodeFirstDataModelProvider)entityMemberParentEntity.DataModel; EFCodeFirstColumnProvider columnProvider; EntityType otherEntityType = navigationProperty.ToEndMember.GetEntityType(); // If we can get to the entityType of the ToMember side of the relaionship then build a relationship key and try to lookup the column provider. if (otherEntityType != null) { long key = BuildRelationshipKey(otherEntityType, navigationProperty.ToEndMember); if (parentEntityModel.RelationshipEndLookup.TryGetValue(key, out columnProvider)) { ToColumn = columnProvider; } else { // Otherwise just lookup the entityType in the table lookup ToTable = parentEntityModel.TableEndLookup[otherEntityType]; } } else { EntityType value = (EntityType)navigationProperty.ToEndMember.TypeUsage.EdmType.MetadataProperties.Single(prop => prop.Name == "ElementType").Value; ToTable = parentEntityModel.TableEndLookup[value]; } if (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) { if (navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) { Direction = AssociationDirection.ManyToMany; } else { Direction = AssociationDirection.OneToMany; } } else { if (navigationProperty.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) { Direction = AssociationDirection.ManyToOne; } else { Direction = AssociationDirection.OneToOne; } } // If it's a foreign key reference (as opposed to a entity set), figure out the foreign keys if (IsForeignKeyReference) { var foreignKeyNames = new List<string>(); var primaryKeyNames = FromColumn.Table.Columns.Where(c => c.IsPrimaryKey).Select(c => c.Name); // Add the foreign keys for this association. foreignKeyNames.AddRange(GetDependentPropertyNames(navigationProperty)); if (IsZeroOrOne(navigationProperty)) { // Assume this is true for 1 to 0..1 relationships on both sides IsPrimaryKeyInThisTable = true; } else { // If any of the foreign keys are also PKs, set the flag IsPrimaryKeyInThisTable = foreignKeyNames.Any(fkName => primaryKeyNames.Contains(fkName, StringComparer.OrdinalIgnoreCase)); } if (!foreignKeyNames.Any()) { // If we couldn't find any dependent properties, we're dealing with a model that doesn't // have FKs, and requires the use of flattened FK names (e.g. Category.CategoryId) foreach (ColumnProvider toEntityColumn in ToTable.Columns.Where(c => c.IsPrimaryKey)) { foreignKeyNames.Add(FromColumn.Name + "." + toEntityColumn.Name); } } ForeignKeyNames = foreignKeyNames.AsReadOnly(); } }