public GetForeignKeyName ( |
||
type | Entity type for which metadata is being generated | |
propertyInfo | Scalar navigation/association property | |
return | string |
/// <summary> /// Make association property metadata for the entity. /// Also populates the ForeignKeyMap which is used for related-entity fixup in NHContext.FixupRelationships /// </summary> /// <param name="propertyInfo">Property info describing the property</param> /// <param name="containingType">Type containing the property</param> /// <param name="dataProperties">Data properties already collected for the containingType. "isPartOfKey" may be added to a property.</param> /// <param name="isKey">Whether the property is part of the key</param> /// <returns></returns> private Dictionary <string, object> MakeAssociationProperty(Type containingType, PropertyInfo propertyInfo, List <Dictionary <string, object> > dataProperties, bool isKey) { var nmap = new Dictionary <string, object>(); var name = propertyInfo.Name; nmap.Add("nameOnServer", name); var propType = propertyInfo.PropertyType; var isCollection = IsCollectionType(propType); var relatedEntityType = isCollection ? GetElementType(propType) : propType; relatedEntityType = _describer.Replace(relatedEntityType, _allTypes); nmap.Add("entityTypeName", relatedEntityType.Name + ":#" + relatedEntityType.Namespace); nmap.Add("isScalar", !isCollection); AddAttributesToNavProperty(propertyInfo, nmap); var entityRelationship = containingType.FullName + '.' + name; // Add assocation. The associationName will be resolved later, when both ends are known. nmap.Add("__association", new Association(containingType, relatedEntityType, name)); if (!isCollection) { // For scalar navigation properties, we need to identify the foreign key var missingFKHandling = _describer.GetMissingFKHandling(containingType, propertyInfo); Dictionary <string, object> dataProp = null; // Find the matching key in the data properties for this entity // First see if a data property was identified on an attribute of the navigation property var fkNames = nmap.Get("foreignKeyNamesOnServer") as string[]; if (fkNames != null) { // find the matching data prop using its fk name var fkName = (fkNames)[0]; dataProp = FindEntry(dataProperties, "nameOnServer", fkName); } if (dataProp == null) { // Next see if a data property was marked as a foreign key during attribute processing dataProp = FindEntry(dataProperties, "__foreignKey", name); } if (dataProp == null) { // Use the descriptor to guess the foreign key var dataPropertyName = _describer.GetForeignKeyName(containingType, propertyInfo); if (dataPropertyName != null) { dataProp = FindEntry(dataProperties, "nameOnServer", dataPropertyName); } } if (dataProp == null && missingFKHandling == MissingKeyHandling.Add) { // Add a new dataproperty to represent the foreign key var dataPropertyName = _describer.GetForeignKeyName(containingType, propertyInfo); dataProp = new Dictionary <string, object>(); dataProp.Add("nameOnServer", dataPropertyName); dataProp.Add("custom", "fk_generated"); string dataType = null; // find the related entity so we can get the datatype of the key var relatedEntityProperties = relatedEntityType.GetProperties(BindingFlags.Public | BindingFlags.Instance); var relatedKey = relatedEntityProperties.Where(p => _describer.IsKeyProperty(relatedEntityType, p)).FirstOrDefault(); if (relatedKey != null) { dataType = _describer.GetDataPropertyType(relatedEntityType, relatedKey).Name; } if (dataType == null) { dataType = "Guid"; } dataProp.Add("dataType", dataType); dataProperties.Add(dataProp); } if (dataProp != null) { fkNames = new string[] { dataProp["nameOnServer"].ToString() }; nmap["foreignKeyNamesOnServer"] = fkNames; dataProp.Remove("__foreignKey"); dataProp.Remove("__relatedType"); // if the navigation property is defined as part of the key, set the fk data property instead if (isKey) { dataProp["isPartOfKey"] = true; } // For many-to-one and one-to-one associations, save the relationship in ForeignKeyMap for re-establishing relationships during save _map.ForeignKeyMap.Add(entityRelationship, string.Join(",", fkNames)); } else { if (missingFKHandling == MissingKeyHandling.Error) { throw new Exception("Cannot find foreign key property on type " + containingType.Name + " for navigation property " + propertyInfo.Name); } else if (missingFKHandling == MissingKeyHandling.Log) { Console.Error.WriteLine("Cannot find foreign key property on type " + containingType.Name + " for navigation property " + propertyInfo.Name); _map.ForeignKeyMap.Add(entityRelationship, "ERROR - NOT FOUND"); } } } return(nmap); }