示例#1
0
        /// <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);
            }
        }
示例#2
0
        /// <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));
 }