/// <summary>
        /// Returns a unique association name for the specified MetaAssociation
        /// </summary>
        /// <param name="metaAssociation">A <see cref="MetaAssociation"/>.</param>
        /// <returns>A <see cref="String"/> containing the association name.</returns>
        private string GetAssociationName(MetaAssociation metaAssociation)
        {
            lock (this._associationNameMap)
            {
                // We need a unique key for this association, so we use the MetaAssociation
                // itself. In the case of bi-directional associations, we use the FK side.
                if (!metaAssociation.IsForeignKey && metaAssociation.OtherMember != null)
                {
                    metaAssociation = metaAssociation.OtherMember.Association;
                }

                string associationName = null;
                if (!this._associationNameMap.TryGetValue(metaAssociation, out associationName))
                {
                    // names are always formatted non-FK side type name followed by FK side type name
                    // For example, the name for both ends of the PurchaseOrder/PurchaseOrderDetail 
                    // association will be PurchaseOrder_PurchaseOrderDetail
                    if (metaAssociation.IsForeignKey)
                    {
                        associationName = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", metaAssociation.OtherType.Name, metaAssociation.ThisMember.DeclaringType.Name);
                    }
                    else
                    {
                        associationName = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", metaAssociation.ThisMember.DeclaringType.Name, metaAssociation.OtherType.Name);
                    }

                    associationName = TypeDescriptionContextBase.MakeUniqueName(associationName, this._associationNameMap.Values);
                    this._associationNameMap[metaAssociation] = associationName;
                }

                return associationName;
            }
        }
        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 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);
     }
 }
Пример #4
0
			internal void Add(MetaAssociation assoc, TrackedObject from, TrackedObject to)
			{
				Dictionary<TrackedObject, TrackedObject> pairs;
				if(!associations.TryGetValue(assoc, out pairs))
				{
					pairs = new Dictionary<TrackedObject, TrackedObject>();
					associations.Add(assoc, pairs);
				}
				pairs.Add(from, to);
			}
Пример #5
0
		internal RelationComposer(ParameterExpression parameter, MetaAssociation association, Expression otherSouce, Expression parameterReplacement) {
			if (parameter==null)
				throw Error.ArgumentNull("parameter");
			if (association == null)
				throw Error.ArgumentNull("association");
			if (otherSouce == null)
				throw Error.ArgumentNull("otherSouce");
			if (parameterReplacement==null)
				throw Error.ArgumentNull("parameterReplacement");
			this.parameter = parameter;
			this.association = association;
			this.otherSouce = otherSouce;
			this.parameterReplacement = parameterReplacement;
		}
Пример #6
0
			internal TrackedObject this[MetaAssociation assoc, TrackedObject from]
			{
				get
				{
					Dictionary<TrackedObject, TrackedObject> pairs;
					if(associations.TryGetValue(assoc, out pairs))
					{
						TrackedObject to;
						if(pairs.TryGetValue(from, out to))
						{
							return to;
						}
					}
					return null;
				}
			}
        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 bool HasAssociationChanged(MetaAssociation assoc, TrackedObject item) {
     if (item.Original != null && item.Current != null) {
         if (assoc.ThisMember.StorageAccessor.HasAssignedValue(item.Current) ||
             assoc.ThisMember.StorageAccessor.HasLoadedValue(item.Current)
             ) {
             return this.GetOtherItem(assoc, item.Current) != this.GetOtherItem(assoc, item.Original);
         }
         else {
             object[] currentFKs = CommonDataServices.GetForeignKeyValues(assoc, item.Current);
             object[] originaFKs = CommonDataServices.GetForeignKeyValues(assoc, item.Original);
             for (int i = 0, n = currentFKs.Length; i < n; i++) {
                 if (!object.Equals(currentFKs[i], originaFKs[i]))
                     return true;
             }
         }
     }
     return false;
 }
 private TrackedObject GetOtherItem(MetaAssociation assoc, object instance) {
     if (instance == null)
         return null;
     object other = null;
     // Don't load unloaded references
     if (assoc.ThisMember.StorageAccessor.HasAssignedValue(instance) ||
         assoc.ThisMember.StorageAccessor.HasLoadedValue(instance)
         ) {
         other = assoc.ThisMember.MemberAccessor.GetBoxedValue(instance);
     }
     else if (assoc.OtherKeyIsPrimaryKey) {
         // Maybe it's in the cache, but not yet attached through reference.
         object[] foreignKeys = CommonDataServices.GetForeignKeyValues(assoc, instance);
         other = this.services.GetCachedObject(assoc.OtherType, foreignKeys);
     }
     // else the other key is not the primary key so there is no way to try to look it up
     return (other != null) ? this.tracker.GetTrackedObject(other) : null;
 }
Пример #10
0
        // Ensure the the member and foreign keys are nulled so that after trackedInstance is deleted,
        // the object does not appear to be associated with the other side anymore. This prevents the deleted object
        // from referencing objects still in the cache, but also will prevent the related object from being implicitly loaded
        private static void ClearForeignKeysHelper(MetaAssociation assoc, object trackedInstance) {            
            Debug.Assert(assoc.IsForeignKey, "Foreign key clearing should only happen on foreign key side of the association.");
            Debug.Assert(assoc.ThisMember.IsAssociation, "Expected ThisMember of an association to always be an association.");
            
            // If this member is one of our deferred loaders, and it does not already have a value, explicitly set the deferred source to
            // null so that when we set the association member itself to null later, it doesn't trigger an implicit load.
            // This is only necessary if the value has not already been assigned or set, because otherwise we won't implicitly load anyway when the member is accessed.
            MetaDataMember thisMember = assoc.ThisMember;

            if (thisMember.IsDeferred &&
                !(thisMember.StorageAccessor.HasAssignedValue(trackedInstance) || thisMember.StorageAccessor.HasLoadedValue(trackedInstance)))
            {
                // If this is a deferred member, set the value directly in the deferred accessor instead of going 
                // through the normal member accessor, so that we don't trigger an implicit load.                                            
                thisMember.DeferredSourceAccessor.SetBoxedValue(ref trackedInstance, null);
            }

            // Notify the object that the relationship should be considered deleted.
            // This allows the object to do its own fixup even when we can't do it automatically.
            thisMember.MemberAccessor.SetBoxedValue(ref trackedInstance, null);

            // Also set the foreign key values to null if possible
            for (int i = 0, n = assoc.ThisKey.Count; i < n; i++) {
                MetaDataMember thisKey = assoc.ThisKey[i];
                if (thisKey.CanBeNull) {
                    thisKey.StorageAccessor.SetBoxedValue(ref trackedInstance, null);
                }
            }
        }
 public void SetAssociation(MetaAssociation association)
 {
     metaAssociation = association;
 }
Пример #12
0
        /// <summary>
        /// Create an Expression representing the given association and key value expressions.
        /// </summary>
        internal static Expression TranslateAssociation(DataContext context, MetaAssociation association, Expression otherSource, Expression[] keyValues, Expression thisInstance) {
            if (association == null)
                throw Error.ArgumentNull("association");
            if (keyValues == null)
                throw Error.ArgumentNull("keyValues");

            if (context.LoadOptions!=null) {
                LambdaExpression subquery = context.LoadOptions.GetAssociationSubquery(association.ThisMember.Member);
                if (subquery!=null) {
                    RelationComposer rc = new RelationComposer(subquery.Parameters[0], association, otherSource, thisInstance);
                    return rc.Visit(subquery.Body);
                }
            }
            return WhereClauseFromSourceAndKeys(otherSource, association.OtherKey.ToArray(), keyValues);
        }
 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;
     }
 }