/// <summary> /// Extension method used to attach the specified entity as modified, /// with the specified original state. /// </summary> /// <typeparam name="T">The entity Type</typeparam> /// <param name="objectSet">The ObjectSet to attach to</param> /// <param name="current">The current entity state</param> /// <param name="original">The original entity state</param> public static void AttachAsModified <T>(this ObjectSet <T> objectSet, T current, T original) where T : class { if (objectSet == null) { throw new ArgumentNullException("objectSet"); } if (current == null) { throw new ArgumentNullException("current"); } if (original == null) { throw new ArgumentNullException("original"); } // Attach the entity if it is not already attached, or if it is already // attached, transition to Modified EntityState currState = ObjectContextUtilities.GetEntityState(objectSet.Context, current); if (currState == EntityState.Detached) { objectSet.Attach(current); } else { objectSet.Context.ObjectStateManager.ChangeObjectState(current, EntityState.Modified); } ObjectStateEntry stateEntry = ObjectContextUtilities.AttachAsModifiedInternal(current, original, objectSet.Context); if (stateEntry.State != EntityState.Modified) { // Ensure that when we leave this method, the entity is in a // Modified state. For example, if current and original are the // same, we still need to force the state transition objectSet.Context.ObjectStateManager.ChangeObjectState(current, EntityState.Modified); } }
/// <summary> /// Extension method used to attach the specified entity as modified. This overload /// can be used in cases where the entity has a Timestamp member. /// </summary> /// <typeparam name="T">The entity Type</typeparam> /// <param name="objectSet">The ObjectSet to attach to</param> /// <param name="entity">The current entity state</param> public static void AttachAsModified <T>(this ObjectSet <T> objectSet, T entity) where T : class { if (objectSet == null) { throw new ArgumentNullException("objectSet"); } if (entity == null) { throw new ArgumentNullException("entity"); } ObjectContext context = objectSet.Context; EntityState currState = ObjectContextUtilities.GetEntityState(context, entity); if (currState == EntityState.Detached) { // attach the entity objectSet.Attach(entity); } // transition the entity to the modified state context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified); }
/// <summary> /// Returns a collection of all the <see cref="Attribute"/>s we infer from the metadata associated /// with the metadata member corresponding to the given property descriptor /// </summary> /// <param name="pd">A <see cref="System.ComponentModel.PropertyDescriptor"/> to examine</param> /// <returns>A collection of attributes inferred from the metadata in the given descriptor.</returns> protected override IEnumerable <Attribute> GetMemberAttributes(PropertyDescriptor pd) { var attributes = new List <Attribute>(); // Exclude any EntityState, EntityReference, etc. members if (ShouldExcludeEntityMember(pd)) { // for these members, we don't want to do any attribute inference return(attributes.ToArray()); } EditableAttribute editableAttribute = null; var inferRoundtripOriginalAttribute = false; var hasKeyAttribute = (pd.Attributes[typeof(KeyAttribute)] != null); var isEntity = EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType; if (isEntity) { var entityType = (EntityType)EdmType; var keyMember = entityType.KeyMembers.SingleOrDefault(k => k.Name == pd.Name); if (keyMember != null && !hasKeyAttribute) { attributes.Add(new KeyAttribute()); hasKeyAttribute = true; } } var member = EdmType.Members.SingleOrDefault(p => p.Name == pd.Name) as EdmProperty; if (member != null) { if (hasKeyAttribute) { ; // key members that aren't also FK members are non-editable (but allow an initial value) if (!_keyIsEditable) { editableAttribute = new EditableAttribute(false) { AllowInitialValue = true }; } } // Check if the member is DB generated and add the DatabaseGeneratedAttribute to it if not already present. if (pd.Attributes[typeof(DatabaseGeneratedAttribute)] == null) { var md = ObjectContextUtilities.GetStoreGeneratedPattern(member); if (md != null) { if ((string)md.Value == "Computed") { attributes.Add(new DatabaseGeneratedAttribute(DatabaseGeneratedOption.Computed)); } else if ((string)md.Value == "Identity") { attributes.Add(new DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)); } } } // Add implicit ConcurrencyCheck attribute to metadata if ConcurrencyMode is anything other than ConcurrencyMode.None var facet = member.TypeUsage.Facets.SingleOrDefault(p => p.Name == "ConcurrencyMode"); if (facet != null && facet.Value != null && (ConcurrencyMode)facet.Value != ConcurrencyMode.None && pd.Attributes[typeof(ConcurrencyCheckAttribute)] == null) { attributes.Add(new ConcurrencyCheckAttribute()); inferRoundtripOriginalAttribute = true; } var isStringType = pd.PropertyType == typeof(string) || pd.PropertyType == typeof(char[]); // Add Required attribute to metdata if the member cannot be null and it is either a reference type or a Nullable<T> if (!member.Nullable && (!pd.PropertyType.IsValueType || IsNullableType(pd.PropertyType)) && pd.Attributes[typeof(RequiredAttribute)] == null) { attributes.Add(new RequiredAttribute()); } if (isStringType && pd.Attributes[typeof(StringLengthAttribute)] == null) { facet = member.TypeUsage.Facets.SingleOrDefault(p => p.Name == "MaxLength"); if (facet != null && facet.Value != null && facet.Value is int) { // need to test for Type int, since the value can also be of type // System.Data.Metadata.Edm.EdmConstants.Unbounded var maxLength = (int)facet.Value; attributes.Add(new StringLengthAttribute(maxLength)); } } var hasTimestampAttribute = (pd.Attributes[typeof(TimestampAttribute)] != null); if (_timestampMember == member && !hasTimestampAttribute) { attributes.Add(new TimestampAttribute()); hasTimestampAttribute = true; } // All members marked with TimestampAttribute (inferred or explicit) need to // have [Editable(false)] and [RoundtripOriginal] applied if (hasTimestampAttribute) { if (editableAttribute == null) { editableAttribute = new EditableAttribute(false); } } } // Add the Editable attribute if required if (editableAttribute != null && pd.Attributes[typeof(EditableAttribute)] == null) { attributes.Add(editableAttribute); } if (isEntity) { AddAssociationAttributes(pd, attributes); } return(attributes.ToArray()); }
/// <summary> /// Returns the <see cref="StructuralType"/> that corresponds to the given CLR type /// </summary> /// <param name="clrType">The CLR type</param> /// <returns>The StructuralType that corresponds to the given CLR type</returns> public StructuralType GetEdmType(Type clrType) { return(ObjectContextUtilities.GetEdmType(MetadataWorkspace, clrType)); }