/// <summary>
		/// Returns a list of keys from the given meta type based on the key list string.
		/// </summary>
		/// <param name="keyListString">The key list string.</param>
		/// <param name="parentType">Type of the parent.</param>
		/// <returns></returns>
		private static ReadOnlyCollection<MetaDataMember> GetKeys(string keyListString, MetaType parentType)
		{
			if(keyListString != null)
			{
				var thisKeyList = new List<MetaDataMember>();

				string[] keyNames = keyListString.Split(STRING_SEPERATOR, StringSplitOptions.RemoveEmptyEntries);

				foreach (string rawKeyName in keyNames)
				{
					string keyName = rawKeyName.Trim();

					//TODO: maybe speed the lookup up
					MetaDataMember key = (from dataMember in parentType.PersistentDataMembers
					             where dataMember.Name == keyName
					             select dataMember).SingleOrDefault();

					if(key == null)
					{
						string errorMessage = string.Format("Could not find key member '{0}' of key '{1}' on type '{2}'. The key may be wrong or the field or property on '{2}' has changed names.",
							keyName, keyListString, parentType.Type.Name);

						throw new InvalidOperationException(errorMessage);
					}

					thisKeyList.Add(key);
				}

				return new ReadOnlyCollection<MetaDataMember>(thisKeyList);
			}
			else //Key is the primary key of this table
			{
				return parentType.IdentityMembers;
			}
		}
		public AttributedColumnMetaDataMember(MemberInfo member, ColumnAttribute attribute, MetaType declaringType)
            : base(member, declaringType, attribute)
        {
            columnAttribute = attribute;
            if (columnAttribute.Name == null)
                columnAttribute.Name = memberInfo.Name;
        }
示例#3
0
		internal SqlTable(MetaTable table, MetaType rowType, ProviderType sqlRowType, Expression sourceExpression)
			: base(SqlNodeType.Table, sourceExpression) {
			this.table = table;
			this.rowType = rowType;
			this.sqlRowType = sqlRowType;
			this.columns = new List<SqlColumn>();
			}
 public AttributedColumnMetaDataMember(MemberInfo member, ColumnAttribute attribute, MetaType declaringType)
     : base(member, declaringType, member.DeclaringType.GetSingleMember(attribute.Storage))
 {
     columnAttribute = attribute;
     if (columnAttribute.Name == null)
         columnAttribute.Name = memberInfo.Name;
 }
		internal static MetaType FindBase(MetaType derivedType)
		{
			if(derivedType.Type == typeof(object))
			{
				return null;
			}

			var clrType = derivedType.Type; // start
			var rootClrType = derivedType.InheritanceRoot.Type; // end
			var metaTable = derivedType.Table;
			MetaType metaType = null;

			while(true)
			{
				if(clrType == typeof(object) || clrType == rootClrType)
				{
					return null;
				}

				clrType = clrType.BaseType;
				metaType = derivedType.InheritanceRoot.GetInheritanceType(clrType);

				if(metaType != null)
				{
					return metaType;
				}
			}
		}
        public DLinqTableProvider(DLinqDataModelProvider dataModel, MetaType rowType, string name, PropertyInfo prop)
            : base(dataModel) {
            _prop = prop;
            _rowType = rowType;
            Name = name;
            DataContextPropertyName = prop.Name;
            EntityType = rowType.Type;
            ParentEntityType = rowType.InheritanceBase != null ? rowType.InheritanceBase.Type : null;
            RootEntityType = rowType.Table.RowType.Type;

            _columns = new List<ColumnProvider>();
            var members = new List<MetaDataMember>(rowType.DataMembers);

            // Add in base-class-first order (not the typical derived-class-first order)
            foreach (PropertyInfo propInfo in GetOrderedProperties(rowType.Type)) {
                MetaDataMember member = members.FirstOrDefault(m => m.Member.Name == propInfo.Name);
                if (member != null) {
                    AddColumn(dataModel, member, propInfo);
                    members.Remove(member);
                }
            }

            // Anything we might've missed, tack it onto the end
            foreach (MetaDataMember member in members) {
                AddColumn(dataModel, member, (PropertyInfo)member.Member);
            }

            _roColumns = new ReadOnlyCollection<ColumnProvider>(_columns);
        }
		internal UnmappedDataMember(MetaType declaringType, MemberInfo mi, int ordinal)
		{
			this.declaringType = declaringType;
			this.member = mi;
			this.ordinal = ordinal;
			this.type = TypeSystem.GetMemberType(mi);
		}
 /// <summary>
 /// Given a type root and a discriminator, return the type that would be instantiated.
 /// </summary>
 private static MetaType TypeFromDiscriminator(MetaType root, object discriminator) {
     foreach (MetaType type in root.InheritanceTypes) {
         if (IsSameDiscriminator(discriminator, type.InheritanceCode))
             return type;
     }
     return root.InheritanceDefault;
 }
 public RepositoryMetaType(string workspace, MetaType original, MetaTable table, MetaModel metaModel)
 {
     this.Workspace = workspace;
     this.Original = original;
     this.RepositoryMetaTable = table;
     this.RepositoryMetaModel = metaModel;
 }
		public override bool IsDeclaredBy(MetaType metaType)
		{
			if(metaType == null)
			{
				throw Error.ArgumentNull("metaType");
			}
			return metaType.Type == this.member.DeclaringType;
		}
		internal AttributedMetaAssociation(AttributedMetaDataMember member, AssociationAttribute attr)
		{
			this.thisMember = member;

			this.isMany = TypeSystem.IsSequenceType(this.thisMember.Type);
			Type ot = this.isMany ? TypeSystem.GetElementType(this.thisMember.Type) : this.thisMember.Type;
			this.otherType = this.thisMember.DeclaringType.Model.GetMetaType(ot);
			this.thisKey = (attr.ThisKey != null) ? MakeKeys(this.thisMember.DeclaringType, attr.ThisKey) : this.thisMember.DeclaringType.IdentityMembers;
			this.otherKey = (attr.OtherKey != null) ? MakeKeys(otherType, attr.OtherKey) : this.otherType.IdentityMembers;
			this.thisKeyIsPrimaryKey = AreEqual(this.thisKey, this.thisMember.DeclaringType.IdentityMembers);
			this.otherKeyIsPrimaryKey = AreEqual(this.otherKey, this.otherType.IdentityMembers);
			this.isForeignKey = attr.IsForeignKey;

			this.isUnique = attr.IsUnique;
			this.deleteRule = attr.DeleteRule;
			this.deleteOnNull = attr.DeleteOnNull;

			// if any key members are not nullable, the association is not nullable
			foreach(MetaDataMember mm in thisKey)
			{
				if(!mm.CanBeNull)
				{
					this.isNullable = false;
					break;
				}
			}

			// validate DeleteOnNull specification
			if(deleteOnNull == true)
			{
				if(!(isForeignKey && !isMany && !isNullable))
				{
					throw Error.InvalidDeleteOnNullSpecification(member);
				}
			}

			//validate the number of ThisKey columns is the same as the number of OtherKey columns
			if(this.thisKey.Count != this.otherKey.Count && this.thisKey.Count > 0 && this.otherKey.Count > 0)
			{
				throw Error.MismatchedThisKeyOtherKey(member.Name, member.DeclaringType.Name);
			}

			// determine reverse reference member
			foreach(MetaDataMember omm in this.otherType.PersistentDataMembers)
			{
				AssociationAttribute oattr = (AssociationAttribute)Attribute.GetCustomAttribute(omm.Member, typeof(AssociationAttribute));
				if(oattr != null)
				{
					if(omm != this.thisMember && oattr.Name == attr.Name)
					{
						this.otherMember = omm;
						break;
					}
				}
			}
		}
示例#12
0
		internal MappedDataMember(MetaType declaringType, MemberInfo mi, MemberMapping map, int ordinal)
		{
			this.declaringType = declaringType;
			this.member = mi;
			this.ordinal = ordinal;
			this.type = TypeSystem.GetMemberType(mi);
			this.isNullableType = TypeSystem.IsNullableType(this.type);
			this.memberMap = map;
			if(this.memberMap != null && this.memberMap.StorageMemberName != null)
			{
				MemberInfo[] mis = mi.DeclaringType.GetMember(this.memberMap.StorageMemberName, BindingFlags.Instance | BindingFlags.NonPublic);
				if(mis == null || mis.Length != 1)
				{
					throw Error.BadStorageProperty(this.memberMap.StorageMemberName, mi.DeclaringType, mi.Name);
				}
				this.storageMember = mis[0];
			}
			Type storageType = this.storageMember != null ? TypeSystem.GetMemberType(this.storageMember) : this.type;
			this.isDeferred = IsDeferredType(storageType);
			ColumnMapping cmap = map as ColumnMapping;
			if(cmap != null && cmap.IsDbGenerated && cmap.IsPrimaryKey)
			{
				// auto-gen identities must be synced on insert
				if((cmap.AutoSync != AutoSync.Default) && (cmap.AutoSync != AutoSync.OnInsert))
				{
					throw Error.IncorrectAutoSyncSpecification(mi.Name);
				}
			}
			if(cmap != null)
			{
				this.isPrimaryKey = cmap.IsPrimaryKey;
				this.isVersion = cmap.IsVersion;
				this.isDBGenerated = cmap.IsDbGenerated || !string.IsNullOrEmpty(cmap.Expression) || this.isVersion;
				this.isDiscriminator = cmap.IsDiscriminator;
				this.canBeNull = cmap.CanBeNull == null ? this.isNullableType || !this.type.IsValueType : (bool)cmap.CanBeNull;
				this.dbType = cmap.DbType;
				this.expression = cmap.Expression;
				this.updateCheck = cmap.UpdateCheck;
				// auto-gen keys are always and only synced on insert
				if(this.IsDbGenerated && this.IsPrimaryKey)
				{
					this.autoSync = AutoSync.OnInsert;
				}
				else if(cmap.AutoSync != AutoSync.Default)
				{
					// if the user has explicitly set it, use their value
					this.autoSync = cmap.AutoSync;
				}
				else if(this.IsDbGenerated)
				{
					// database generated members default to always
					this.autoSync = AutoSync.Always;
				}
			}
			this.mappedName = this.memberMap.DbName != null ? this.memberMap.DbName : this.member.Name;
		}
		internal SqlDiscriminatedType(ProviderType sqlType, SqlExpression discriminator, MetaType targetType, Expression sourceExpression)
			: base(SqlNodeType.DiscriminatedType,
				typeof(Type),
				sourceExpression) {
			if (discriminator == null)
				throw Error.ArgumentNull("discriminator");
			this.discriminator = discriminator;
			this.targetType = targetType;
			this.sqlType = sqlType;
				}
示例#14
0
		internal SqlTypeCase(Type clrType, ProviderType sqlType, MetaType rowType, SqlExpression discriminator, IEnumerable<SqlTypeCaseWhen> whens, Expression sourceExpression)
			: base(SqlNodeType.TypeCase, clrType, sourceExpression) {
			this.Discriminator = discriminator;
			if (whens == null)
				throw Error.ArgumentNull("whens");
			this.whens.AddRange(whens);
			if (this.whens.Count == 0)
				throw Error.ArgumentOutOfRange("whens");
			this.sqlType = sqlType;
			this.rowType = rowType;
			}
示例#15
0
		internal SqlLink(object id, MetaType rowType, Type clrType, ProviderType sqlType, SqlExpression expression, MetaDataMember member, IEnumerable<SqlExpression> keyExpressions, SqlExpression expansion, Expression sourceExpression)
			: base(SqlNodeType.Link, clrType, sqlType, sourceExpression) {
			this.id = id;
			this.rowType = rowType;
			this.expansion = expansion;
			this.expression = expression;
			this.member = member;
			this.keyExpressions = new List<SqlExpression>();
			if (keyExpressions != null)
				this.keyExpressions.AddRange(keyExpressions);
			}
示例#16
0
		private object locktarget = new object(); // Hold locks on private object rather than public MetaType.
		#endregion

		internal MappedType(MetaModel model, MetaTable table, TypeMapping typeMapping, Type type, MetaType inheritanceRoot)
		{
			this.model = model;
			this.table = table;
			this.typeMapping = typeMapping;
			this.type = type;
			this.inheritanceRoot = inheritanceRoot != null ? inheritanceRoot : this;
			this.InitDataMembers();

			this.identities = this.dataMembers.Where(m => m.IsPrimaryKey).ToList().AsReadOnly();
			this.persistentDataMembers = this.dataMembers.Where(m => m.IsPersistent).ToList().AsReadOnly();
		}
		object locktarget = new object(); // Hold locks on private object rather than public MetaType.

		internal AttributedMetaType(MetaModel model, MetaTable table, Type type, MetaType inheritanceRoot)
		{
			this.model = model;
			this.table = table;
			this.type = type;
			this.inheritanceRoot = (inheritanceRoot != null) ? inheritanceRoot : this;
			// Not lazy-loading to simplify locking and enhance performance 
			// (because no lock will be required for the common read scenario).
			this.InitDataMembers();
			this.identities = this.dataMembers.Where(m => m.IsPrimaryKey).ToList().AsReadOnly();
			this.persistentMembers = this.dataMembers.Where(m => m.IsPersistent).ToList().AsReadOnly();
		}
示例#18
0
        internal SqlSelect BuildDefaultQuery(MetaType rowType, bool allowDeferred, SqlLink link, Expression source) {
            System.Diagnostics.Debug.Assert(rowType != null && rowType.Table != null);
            if (rowType.HasInheritance && rowType.InheritanceRoot != rowType) {
                // RowType is expected to be an inheritance root.
                throw Error.ArgumentWrongValue("rowType");
            }
            SqlTable table = sql.Table(rowType.Table, rowType, source);
            SqlAlias tableAlias = new SqlAlias(table);
            SqlAliasRef tableAliasRef = new SqlAliasRef(tableAlias);

            SqlExpression projection = this.BuildProjection(tableAliasRef, table.RowType, allowDeferred, link, source);
            return new SqlSelect(projection, tableAlias, source);
        }
		protected AttributedAbstractMetaDataMember(MemberInfo member, MetaType declaringType, DataAttribute attribute)
		{
			memberInfo = member;
			memberAccessor = LambdaMetaAccessor.Create(member, declaringType.Type);
			this.declaringType = declaringType;
			
			if(attribute.Storage != null)
			{
				storageMember = member.DeclaringType.GetSingleMember(attribute.Storage);
				if (storageMember != null)
					storageAccessor = LambdaMetaAccessor.Create(storageMember, declaringType.Type);
			}
		}
        public AttributedMetaTable(TableAttribute attribute, MetaType type, MetaModel model)
        {
            _tableAttribute = attribute;
            _metaType = type;
        	_containingModel = model;

			//If the attribute doesn't specify a table name the name of the table class is used
			if(!string.IsNullOrEmpty(attribute.Name))
			{
				_tableName = attribute.Name;
			}
			else
			{
				_tableName = type.Name;
			}
        }
		private void SetCurrent(MetaType type)
		{
			type = type.InheritanceRoot;
			if(this.currentType != type)
			{
				if(!this.caches.TryGetValue(type, out this.currentCache))
				{
					KeyManager km = GetKeyManager(type);
					this.currentCache = (IdentityCache)Activator.CreateInstance(
						typeof(IdentityCache<,>).MakeGenericType(type.Type, km.KeyType),
						BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null,
						new object[] { km }, null
						);
					this.caches.Add(type, this.currentCache);
				}
				this.currentType = type;
			}
		}
		/// <summary>
		/// Given a MetaType and a set of key fields, return the set of MetaDataMembers
		/// corresponding to the key.
		/// </summary>
		protected static ReadOnlyCollection<MetaDataMember> MakeKeys(MetaType mtype, string keyFields)
		{
			string[] names = keyFields.Split(keySeparators);
			MetaDataMember[] members = new MetaDataMember[names.Length];
			for(int i = 0; i < names.Length; i++)
			{
				names[i] = names[i].Trim();
				MemberInfo[] rmis = mtype.Type.GetMember(names[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if(rmis == null || rmis.Length != 1)
				{
					throw Error.BadKeyMember(names[i], keyFields, mtype.Name);
				}
				members[i] = mtype.GetDataMember(rmis[0]);
				if(members[i] == null)
				{
					throw Error.BadKeyMember(names[i], keyFields, mtype.Name);
				}
			}
			return new List<MetaDataMember>(members).AsReadOnly();
		}
示例#23
0
		private void InitOther()
		{
			if(this.otherType == null)
			{
				Type ot = this.isMany ? TypeSystem.GetElementType(this.thisMember.Type) : this.thisMember.Type;
				this.otherType = this.thisMember.DeclaringType.Model.GetMetaType(ot);
				System.Diagnostics.Debug.Assert(this.otherType.IsEntity);
				this.otherKey = (assocMap.OtherKey != null)
					? MakeKeys(this.otherType, this.assocMap.OtherKey)
					: this.otherType.IdentityMembers;
				this.otherKeyIsPrimaryKey = AreEqual(this.otherKey, this.otherType.IdentityMembers);
				foreach(MetaDataMember omm in this.otherType.DataMembers)
				{
					if(omm.IsAssociation && omm != this.thisMember && omm.MappedName == this.thisMember.MappedName)
					{
						this.otherMember = omm;
						break;
					}
				}
			}
		}
示例#24
0
		internal SqlNew(MetaType metaType, ProviderType sqlType, ConstructorInfo cons, IEnumerable<SqlExpression> args, IEnumerable<MemberInfo> argMembers, IEnumerable<SqlMemberAssign> members, Expression sourceExpression)
			: base(SqlNodeType.New, metaType.Type, sqlType, sourceExpression) {
			this.metaType = metaType;
            
			if (cons == null && metaType.Type.IsClass) { // structs do not need to have a constructor
				throw Error.ArgumentNull("cons");
			}
			this.constructor = cons;
			this.args = new List<SqlExpression>();
			this.argMembers = new List<MemberInfo>();
			this.members = new List<SqlMemberAssign>();
			if (args != null) {
				this.args.AddRange(args);
			}
			if (argMembers != null) {
				this.argMembers.AddRange(argMembers);
			}
			if (members != null) {
				this.members.AddRange(members);
			}
			}
		static KeyManager GetKeyManager(MetaType type)
		{
			int n = type.IdentityMembers.Count;
			MetaDataMember mm = type.IdentityMembers[0];

			KeyManager km = (KeyManager)Activator.CreateInstance(
						typeof(SingleKeyManager<,>).MakeGenericType(type.Type, mm.Type),
						BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null,
						new object[] { mm.StorageAccessor, 0 }, null
						);
			for(int i = 1; i < n; i++)
			{
				mm = type.IdentityMembers[i];
				km = (KeyManager)
					Activator.CreateInstance(
						typeof(MultiKeyManager<,,>).MakeGenericType(type.Type, mm.Type, km.KeyType),
						BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null,
						new object[] { mm.StorageAccessor, i, km }, null
						);
			}

			return km;
		}
		private TrackedObject Track(MetaType mt, object obj, Dictionary<object, object> visited, bool recurse, int level)
		{
			StandardTrackedObject tracked = (StandardTrackedObject)this.GetTrackedObject(obj);
			if(tracked != null || visited.ContainsKey(obj))
			{
				return tracked;
			}

			// The root object tracked is tracked normally - all other objects
			// in the reference graph are weakly tracked.
			bool weaklyTrack = level > 1;
			tracked = new StandardTrackedObject(this, mt, obj, obj, weaklyTrack);
			if(tracked.HasDeferredLoaders)
			{
				throw Error.CannotAttachAddNonNewEntities();
			}
			this.items.Add(obj, tracked);
			this.Attach(obj);
			visited.Add(obj, obj);

			if(recurse)
			{
				// track parents (objects we are dependent on)
				foreach(RelatedItem parent in this.services.GetParents(mt, obj))
				{
					this.Track(parent.Type, parent.Item, visited, recurse, level + 1);
				}

				// track children (objects that are dependent on us)
				foreach(RelatedItem child in this.services.GetChildren(mt, obj))
				{
					this.Track(child.Type, child.Item, visited, recurse, level + 1);
				}
			}

			return tracked;
		}
示例#27
0
        internal SqlExpression BuildProjection(SqlExpression item, MetaType rowType, bool allowDeferred, SqlLink link, Expression source) {
            if (!rowType.HasInheritance) {
                return this.BuildProjectionInternal(item, rowType, (rowType.Table != null) ? rowType.PersistentDataMembers : rowType.DataMembers, allowDeferred, link, source);
            }
            else {
                // Build a type case that represents a switch between the various type.
                List<MetaType> mappedTypes = new List<MetaType>(rowType.InheritanceTypes);
                List<SqlTypeCaseWhen> whens = new List<SqlTypeCaseWhen>();
                SqlTypeCaseWhen @else = null;

                MetaType root = rowType.InheritanceRoot;
                MetaDataMember discriminator = root.Discriminator;
                Type dt = discriminator.Type;
                SqlMember dm = sql.Member(item, discriminator.Member);

                foreach (MetaType type in mappedTypes) {
                    if (type.HasInheritanceCode) {
                        SqlNew defaultProjection = this.BuildProjectionInternal(item, type, type.PersistentDataMembers, allowDeferred, link, source);
                        if (type.IsInheritanceDefault) {
                            @else = new SqlTypeCaseWhen(null, defaultProjection);
                        }
                        // Add an explicit case even for the default.
                        // Redundant results will be optimized out later.
                        object code = InheritanceRules.InheritanceCodeForClientCompare(type.InheritanceCode, dm.SqlType);
                        SqlExpression match = sql.Value(dt, sql.Default(discriminator), code, true, source);
                        whens.Add(new SqlTypeCaseWhen(match, defaultProjection));
                    }
                }
                if (@else == null) {
                    throw Error.EmptyCaseNotSupported();
                }
                whens.Add(@else);   // Add the else at the end.
                
                return sql.TypeCase(root.Type, root, dm, whens.ToArray(), source);
            }
        }
        private void ObserveUntrackedObjects(MetaType type, object item, Dictionary<object, object> visited) {
            if (!visited.ContainsKey(item)) {
                visited.Add(item, item);
                TrackedObject tracked = this.tracker.GetTrackedObject(item);
                if (tracked == null) {
                    tracked = this.tracker.Track(item);
                    tracked.ConvertToNew();
                } else if (tracked.IsDead || tracked.IsRemoved) {
                    // ignore
                    return;
                }

                // search parents (objects we are dependent on)
                foreach (RelatedItem parent in this.services.GetParents(type, item)) {
                    this.ObserveUntrackedObjects(parent.Type, parent.Item, visited);
                }

                // synch up primary key unless its generated.
                if (tracked.IsNew) {
                     if (!tracked.IsPendingGeneration(tracked.Type.IdentityMembers)) {
                        tracked.SynchDependentData();
                     } 
                }

                // search children (objects that are dependent on us)
                foreach (RelatedItem child in this.services.GetChildren(type, item)) {
                    this.ObserveUntrackedObjects(child.Type, child.Item, visited);
                }
            }
        }
        private void TrackUntrackedObjects(MetaType type, object item, Dictionary<object, object> visited) {
            if (!visited.ContainsKey(item)) {
                visited.Add(item, item);
                TrackedObject tracked = this.tracker.GetTrackedObject(item);
                if (tracked == null) {
                    tracked = this.tracker.Track(item);
                    tracked.ConvertToNew();
                }
                else if (tracked.IsDead || tracked.IsRemoved) {
                    // ignore
                    return;
                }

                // search parents (objects we are dependent on)
                foreach (RelatedItem parent in this.services.GetParents(type, item)) {
                    this.TrackUntrackedObjects(parent.Type, parent.Item, visited);
                }

                // synch up primary key
                if (tracked.IsNew) {
                    tracked.InitializeDeferredLoaders();

                    if (!tracked.IsPendingGeneration(tracked.Type.IdentityMembers)) {
                        tracked.SynchDependentData();
                        object cached = this.services.InsertLookupCachedObject(tracked.Type, item);
                        if (cached != item) {
                            TrackedObject cachedTracked = this.tracker.GetTrackedObject(cached);
                            Debug.Assert(cachedTracked != null);
                            if (cachedTracked.IsDeleted || cachedTracked.CanInferDelete()) {
                                // adding new object with same ID as object being deleted.. turn into modified
                                tracked.ConvertToPossiblyModified(cachedTracked.Original);
                                // turn deleted to dead...
                                cachedTracked.ConvertToDead();

                                this.services.RemoveCachedObjectLike(tracked.Type, item);
                                this.services.InsertLookupCachedObject(tracked.Type, item);
                            }
                            else if (!cachedTracked.IsDead) {
                                throw new DuplicateKeyException(item, Strings.CantAddAlreadyExistingKey);
                            }
                        }
                    }
                    else {
                        // we may have a generated PK, however we set the PK on this new item to 
                        // match a deleted item
                        object cached = this.services.GetCachedObjectLike(tracked.Type, item);
                        if (cached != null) {
                            TrackedObject cachedTracked = this.tracker.GetTrackedObject(cached);
                            Debug.Assert(cachedTracked != null);
                            if (cachedTracked.IsDeleted || cachedTracked.CanInferDelete()) {
                                // adding new object with same ID as object being deleted.. turn into modified
                                tracked.ConvertToPossiblyModified(cachedTracked.Original);
                                // turn deleted to dead...
                                cachedTracked.ConvertToDead();

                                this.services.RemoveCachedObjectLike(tracked.Type, item);
                                this.services.InsertLookupCachedObject(tracked.Type, item);
                            }
                        }
                    }
                }

                // search children (objects that are dependent on us)
                foreach (RelatedItem child in this.services.GetChildren(type, item)) {
                    this.TrackUntrackedObjects(child.Type, child.Item, visited);
                }
            }
        }
        private static void SendOnValidate(MetaType type, TrackedObject item, ChangeAction changeAction) {
            if (type != null) {
                SendOnValidate(type.InheritanceBase, item, changeAction);

                if (type.OnValidateMethod != null) {
                    try {
                        type.OnValidateMethod.Invoke(item.Current, new object[] { changeAction });
                    } catch (TargetInvocationException tie) {
                        if (tie.InnerException != null) {
                            throw tie.InnerException;
                        }

                        throw;
                    }
                }
            }
        }
示例#31
0
 public abstract bool IsDeclaredBy(MetaType type);