/// <summary>
    /// Validates a single entity.
    /// Skips validation (returns true) if entity is marked Deleted.
    /// </summary>
    /// <param name="entityInfo">contains the entity to validate</param>
    /// <param name="entityErrors">An EntityError is added to this list for each error found in the entity</param>
    /// <returns>true if entity is valid, false if invalid.</returns>
    public bool ValidateEntity(EntityInfo entityInfo, List<EntityError> entityErrors) {
      if (entityInfo.EntityState == EntityState.Deleted) return true;
      bool isValid = true;
      var entity = entityInfo.Entity;
      var entityType = entity.GetType();
      var entityTypeName = entityType.FullName;
      var sType = _structuralTypeMap[entityTypeName];
      var dataProperties = sType.dataProperties;
      object[] keyValues = null;
      foreach (var dp in sType.dataProperties) {
        if (dp.validators == null) continue;
        if (dp.propertyInfo == null) {
          dp.propertyInfo = entityType.GetProperty(dp.name);  // try converting from camelCase?
          if (dp.propertyInfo == null) continue;
        }
        var value = dp.propertyInfo.GetValue(entity, null);

        foreach (var validator in dp.validators) {
          var errorMessage = validator.Validate(value);
          if (errorMessage != null) {
            if (keyValues == null) keyValues = _contextProvider.GetKeyValues(entityInfo);

            entityErrors.Add(new EntityError() {
              EntityTypeName = entityTypeName,
              ErrorMessage = errorMessage,
              ErrorName = "ValidationError",
              KeyValues = keyValues,
              PropertyName = dp.name
            });
            isValid = false;
          }
        }
      }
      return isValid;
    }
示例#2
0
 private string CanSaveExistingEntity(EntityInfo arg)
 {
     var type = arg.Entity.GetType();
     if (type == typeof(Customer))
     {
         return ExistingCustomerSaveGuard(arg);
     }
     if (type == typeof(Employee))
     {
         return ExistingEmployeeSaveGuard(arg);
     }
     if (type == typeof(Order))
     {
         return ExistingOrderSaveGuard(arg);
     }
     if (type == typeof(OrderDetail))
     {
         return ExistingOrderDetailSaveGuard(arg);
     }
     if (type == typeof(InternationalOrder))
     {
         return ExistingInternationalOrderSaveGuard(arg);
     }
     if (type == typeof(User))
     {
         return ExistingUserSaveGuard(arg);
     }
     return "is is not a saveable type";
 }
示例#3
0
        public bool BeforeSaveEntity(EntityInfo entityInfo)
        {
            // Add custom logic here in order to save entities
            // Return false if don´t want to  save the entity

            return true;
        }
 // Todo: delegate to helper classes when it gets more complicated
 protected override bool BeforeSaveEntity(EntityInfo entityInfo) {
   var entity = entityInfo.Entity;
   if (entity is TodoList) { return true; }
   if (entity is TodoItem) {
     return BeforeSaveTodoItem(entity as TodoItem, entityInfo);
   }
   throw new InvalidOperationException("Cannot save entity of unknown type");
 }
 /// <summary>
 /// Add the relationship to the dependencyGraph
 /// </summary>
 /// <param name="child">Entity that depends on parent (e.g. has a many-to-one relationship to parent)</param>
 /// <param name="parent">Entity that child depends on (e.g. one parent has one-to-many children)</param>
 private void AddToGraph(EntityInfo child, EntityInfo parent)
 {
     List<EntityInfo> list;
     if (!dependencyGraph.TryGetValue(child, out list))
     {
         list = new List<EntityInfo>(5);
         dependencyGraph.Add(child, list);
     }
     if (parent != null) list.Add(parent);
 }
        public bool BeforeSaveEntity(EntityInfo entityInfo)
        {
            // Add custom logic here in order to save entities
            // Return false if don´t want to  save the entity 

            // - Before saving articles we have to create the custom UrlCodeReference in order to access them from a url route
            // - Before saving articles we have to fill the Audit info

            if (entityInfo.Entity.GetType() == typeof(Article))
            {
                var article = entityInfo.Entity as Article;

                if (entityInfo.EntityState == EntityState.Added)
                {
                    if (article != null)
                    {
                        article.SetUrlReference();
                        article.CreatedBy = HttpContext.Current.User.Identity.GetUserName();
                        article.CreatedDate = DateTime.UtcNow;
                        article.UpdatedBy = HttpContext.Current.User.Identity.GetUserName();
                        article.UpdatedDate = DateTime.UtcNow;
                    }
                }
                if (entityInfo.EntityState == EntityState.Modified)
                {
                    if (article != null)
                    {
                        article.UpdatedBy = HttpContext.Current.User.Identity.GetUserName();
                        article.UpdatedDate = DateTime.UtcNow;
                    }
                }
            }

            // - Before saving categories we have to create the custom UrlCodeReference in order to access them from a url route

            if (entityInfo.Entity.GetType() != typeof(Category))
            {
                return true;
            }

            var category = entityInfo.Entity as Category;

            if (entityInfo.EntityState != EntityState.Added)
            {
                return true;
            }

            if (category != null)
            {
                category.SetUrlReference();
            }

            return true;
        }
 /// <summary>
 /// Demonstration interceptor - called once for each entity to be saved
 /// </summary>
 /// <returns>
 /// True if can save this entity else throw exception
 /// </returns>
 /// <exception cref="System.InvalidOperationException" />
 private bool BeforeSaveEntity(EntityInfo arg) {
     var todo = arg.Entity as TodoItem;
     if (todo != null && todo.Description.Contains("INTERCEPT")) {
         if (todo.Description.Contains("SAVE")) {
             todo.Description = "INTERCEPT SAVED";
             return true;
         }
         if (todo.Description.Contains("EXCLUDE")) {
             todo.Description = "INTERCEPT EXCLUDED";
             return false;
         }
         if (todo.Description.Contains("FAIL")) {
             throw new InvalidOperationException("Failed due to description contains INTERCEPT FAIL");
         }
     }
     return true;
 }
        /// <summary>
        /// True if can save this entity else throw exception
        /// </summary>
        /// <exception cref="System.InvalidOperationException"></exception>
        public bool BeforeSaveEntity(EntityInfo arg)
        {
            var typeName = arg.Entity.GetType().Name;
            string saveError;
            var saveable = arg.Entity as ISaveable;

            if (UserSessionId == Guid.Empty)
            {
                saveError = "you are not authorized to save.";
            } else if (saveable == null)
            {
                saveError = "changes to '" + typeName + "' are forbidden.";
            }
            else
            {
                switch (arg.EntityState)
                {
                    case EntityState.Added:
                        saveable.UserSessionId = UserSessionId;
                        if (arg.OriginalValuesMap == null) {
                          arg.OriginalValuesMap = new Dictionary<string, object>();
                        }
                        arg.OriginalValuesMap.Add("UserSessionId", UserSessionId);
                        saveError = saveable.CanAdd();
                        break;
                    case EntityState.Modified:
                    case EntityState.Deleted:
                        saveError = CanSaveExistingEntity(arg);
                        break;
                    default:
                        var stateName = Enum.GetName(typeof(EntityState), arg.EntityState);
                        saveError = " unexpected EntityState of " + stateName;
                        break;
                }
            }

            if (!String.IsNullOrEmpty(saveError))
            {
                throw new InvalidOperationException(
                    "'" + arg.Entity.GetType().Name + "' may not be saved because " +
                    saveError);
            }
            return true;
        }
        /// <summary>
        /// Add the relationship to the dependencyGraph
        /// </summary>
        /// <param name="child">Entity that depends on parent (e.g. has a many-to-one relationship to parent)</param>
        /// <param name="parent">Entity that child depends on (e.g. one parent has one-to-many children)</param>
        /// <param name="removeReverse">True to find and remove the reverse relationship.  Used for handling one-to-ones.</param>
        private void AddToGraph(EntityInfo child, EntityInfo parent, bool removeReverse)
        {
            List<EntityInfo> list;
            if (!dependencyGraph.TryGetValue(child, out list))
            {
                list = new List<EntityInfo>(5);
                dependencyGraph.Add(child, list);
            }
            if (parent != null) list.Add(parent);

            if (removeReverse)
            {
                List<EntityInfo> parentList;
                if (dependencyGraph.TryGetValue(parent, out parentList))
                {
                    parentList.Remove(child);
                }
            }
        }
示例#10
0
 /// <summary>
 /// Validates a single entity.
 /// Skips validation (returns true) if entity is marked Deleted.
 /// </summary>
 /// <param name="entityInfo">contains the entity to validate</param>
 /// <param name="entityErrors">An EntityError is added to this list for each error found in the entity</param>
 /// <returns>true if entity is valid, false if invalid.</returns>
 public bool ValidateEntity(EntityInfo entityInfo, List<EntityError> entityErrors) {
   if (entityInfo.EntityState == EntityState.Deleted) return true;
   // Perform validation on the entity, based on DataAnnotations.  
   var entity = entityInfo.Entity;
   var validationResults = new List<ValidationResult>();
   if (!Validator.TryValidateObject(entity, new ValidationContext(entity, null, null), validationResults, true)) {
     var keyValues = _contextProvider.GetKeyValues(entityInfo);
     var entityTypeName = entity.GetType().FullName;
     foreach (var vr in validationResults) {
       entityErrors.Add(new EntityError() {
         EntityTypeName = entityTypeName,
         ErrorMessage = vr.ErrorMessage,
         ErrorName = "ValidationError",
         KeyValues = keyValues,
         PropertyName = vr.MemberNames.FirstOrDefault()
       });
     }
     return false;
   }
   return true;
 }
示例#11
0
 private string ExistingUserSaveGuard(EntityInfo arg)
 {
     var entity = (User)arg.Entity;
     var orig = readContext.Users.SingleOrDefault(e => e.Id == entity.Id);
     return ExistingEntityGuard(orig, entity.Id);
 }
示例#12
0
 private string ExistingInternationalOrderSaveGuard(EntityInfo arg)
 {
     var entity = (InternationalOrder)arg.Entity;
     var orig = readContext.InternationalOrders.SingleOrDefault(e => e.OrderID == entity.OrderID);
     return ExistingEntityGuard(orig, entity.OrderID);
 }
示例#13
0
 private string ExistingOrderDetailSaveGuard(EntityInfo arg)
 {
     var entity = (OrderDetail)arg.Entity;
     var orig = readContext.OrderDetails
                           .SingleOrDefault(e => e.OrderID == entity.OrderID &&
                                                 e.ProductID == entity.ProductID);
     var key = "(" + entity.OrderID + "," + entity.ProductID + ")";
     return ExistingEntityGuard(orig, key);
 }
        /// <summary>
        /// Set an association value based on the value of the foreign key.  This updates the property of the entity.
        /// </summary>
        /// <param name="propName">Name of the navigation/association property of the entity, e.g. "Customer".  May be null if the property is the entity's identifier.</param>
        /// <param name="propType">Type of the property</param>
        /// <param name="entityInfo">Breeze EntityInfo</param>
        /// <param name="meta">Metadata for the entity class</param>
        private void FixupRelationship(string propName, EntityType propType, EntityInfo entityInfo, IClassMetadata meta)
        {
            var entity = entityInfo.Entity;
            if (removeMode)
            {
                meta.SetPropertyValue(entity, propName, null, EntityMode.Poco);
                return;
            }
            object relatedEntity = GetPropertyValue(meta, entity, propName);
            if (relatedEntity != null) return;    // entities are already connected

            relatedEntity = GetRelatedEntity(propName, propType, entityInfo, meta);

            if (relatedEntity != null)
                meta.SetPropertyValue(entity, propName, relatedEntity, EntityMode.Poco);
        }
        /// <summary>
        /// Get the value of the foreign key property.  This comes from the entity, but if that value is
        /// null, and the entity is deleted, we try to get it from the originalValuesMap.
        /// </summary>
        /// <param name="entityInfo">Breeze EntityInfo</param>
        /// <param name="meta">Metadata for the entity class</param>
        /// <param name="foreignKeyName">Name of the foreign key property of the entity, e.g. "CustomerID"</param>
        /// <returns></returns>
        private object GetForeignKeyValue(EntityInfo entityInfo, IClassMetadata meta, string foreignKeyName)
        {
            var entity = entityInfo.Entity;
            object id = null;
            if (foreignKeyName == meta.IdentifierPropertyName)
                id = meta.GetIdentifier(entity, EntityMode.Poco);
            else if (meta.PropertyNames.Contains(foreignKeyName))
                id = meta.GetPropertyValue(entity, foreignKeyName, EntityMode.Poco);
            else if (meta.IdentifierType.IsComponentType)
            {
                // compound key
                var compType = meta.IdentifierType as ComponentType;
                var index = Array.IndexOf<string>(compType.PropertyNames, foreignKeyName);
                if (index >= 0)
                {
                    var idComp = meta.GetIdentifier(entity, EntityMode.Poco);
                    id = compType.GetPropertyValue(idComp, index, EntityMode.Poco);
                }
            }

            if (id == null && entityInfo.EntityState == EntityState.Deleted)
            {
                entityInfo.OriginalValuesMap.TryGetValue(foreignKeyName, out id);
            }
            return id;
        }
 public TempKeyInfo(EntityInfo entityInfo)
 {
     _entityInfo = entityInfo;
 }
        /// <summary>
        /// Connect the related entities based on the foreign key values.
        /// Note that this may cause related entities to be loaded from the DB if they are not already in the session.
        /// </summary>
        /// <param name="entityInfo">Entity that will be saved</param>
        /// <param name="meta">Metadata about the entity type</param>
        private void FixupRelationships(EntityInfo entityInfo, IClassMetadata meta)
        {
            var propNames = meta.PropertyNames;
            var propTypes = meta.PropertyTypes;
            

            if (meta.IdentifierType != null)
            {
                var propType = meta.IdentifierType;
                if (propType.IsAssociationType && propType.IsEntityType)
                {
                    FixupRelationship(meta.IdentifierPropertyName, (EntityType)propType, entityInfo, meta);
                }
                else if (propType.IsComponentType)
                {
                    FixupComponentRelationships(meta.IdentifierPropertyName, (ComponentType)propType, entityInfo, meta);
                }
            }

            for (int i = 0; i < propNames.Length; i++)
            {
                var propType = propTypes[i];
                if (propType.IsAssociationType && propType.IsEntityType)
                {
                    FixupRelationship(propNames[i], (EntityType)propTypes[i], entityInfo, meta);
                }
                else if (propType.IsComponentType)
                {
                    FixupComponentRelationships(propNames[i], (ComponentType)propType, entityInfo, meta);
                }
            }
        }
        /// <summary>
        /// Connect the related entities based on the foreign key values.
        /// Note that this may cause related entities to be loaded from the DB if they are not already in the session.
        /// </summary>
        /// <param name="entityInfo">Entity that will be saved</param>
        /// <param name="meta">Metadata about the entity type</param>
        private void ProcessRelationships(EntityInfo entityInfo, IClassMetadata meta)
        {
            var propNames = meta.PropertyNames;
            var propTypes = meta.PropertyTypes;
            
            if (meta.IdentifierType != null)
            {
                ProcessRelationship(meta.IdentifierPropertyName, meta.IdentifierType, entityInfo, meta);
            }

            for (int i = 0; i < propNames.Length; i++)
            {
                ProcessRelationship(propNames[i], propTypes[i], entityInfo, meta);
            }
        }
 /// <summary>
 /// Handle a specific property if it is a Association or Component relationship.
 /// </summary>
 private void ProcessRelationship(string propName, IType propType, EntityInfo entityInfo, IClassMetadata meta)
 {
     if (propType.IsAssociationType && propType.IsEntityType)
     {
         FixupRelationship(propName, (EntityType)propType, entityInfo, meta);
     }
     else if (propType.IsComponentType)
     {
         FixupComponentRelationships(propName, (ComponentType)propType, entityInfo, meta);
     }
 }
示例#20
0
 public virtual object[] GetKeyValues(EntityInfo entityInfo) {
   throw new NotImplementedException();
 }
示例#21
0
 /// <summary>
 /// The method is called for each entity to be saved before the save occurs.  If this method returns 'false'
 /// then the entity will be excluded from the save.  The base implementation returns the result of BeforeSaveEntityDelegate,
 /// or 'true' if BeforeSaveEntityDelegate is null.
 /// </summary>
 /// <param name="entityInfo"></param>
 /// <returns>true to include the entity in the save, false to exclude</returns>
 protected internal virtual bool BeforeSaveEntity(EntityInfo entityInfo) {
   if (BeforeSaveEntityDelegate != null) {
     return BeforeSaveEntityDelegate(entityInfo);
   } else {
     return true;
   }
 }
 private string ExistingProductSaveGuard(EntityInfo arg) {
   var entity = (Product)arg.Entity;
   var orig = readContext.Products.SingleOrDefault(e => e.ProductID == entity.ProductID);
   return ExistingEntityGuard(orig, entity.ProductID);
 }
 private void setChanged(EntityInfo entityInfo, string property, Object oldValue)
 {
 }
 /// <summary>Add the parent-child relationship for certain propType conditions</summary>
 private void MaybeAddToGraph(EntityInfo child, EntityInfo parent, EntityType propType)
 {
     if (!(propType.IsOneToOne && propType.UseLHSPrimaryKey && (propType.ForeignKeyDirection == ForeignKeyDirection.ForeignKeyToParent)))
     {
         AddToGraph(child, parent);
     }
 }
        /// <summary>
        /// Recursively add entities to the saveOrder or deleteOrder according to their dependencies
        /// </summary>
        /// <param name="entityInfo">Entity to be added.  Its dependencies will be added depth-first.</param>
        /// <param name="depth">prevents infinite recursion in case of cyclic dependencies</param>
        private void AddToSaveOrder(EntityInfo entityInfo, int depth)
        {
            if (saveOrder.Contains(entityInfo)) return;
            if (deleteOrder.Contains(entityInfo)) return;
            if (depth > 10) return;

            var dependencies = dependencyGraph[entityInfo];
            foreach (var dep in dependencies)
            {
                AddToSaveOrder(dep, depth + 1);
            }

            if (entityInfo.EntityState == EntityState.Deleted)
                deleteOrder.Add(entityInfo);
            else
                saveOrder.Add(entityInfo);
        }
 public virtual object[] GetKeyValues(EntityInfo entityInfo)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        /// Connect the related entities based on the foreign key values found in a component type.
        /// This updates the values of the component's properties.
        /// </summary>
        /// <param name="propName">Name of the (component) property of the entity.  May be null if the property is the entity's identifier.</param>
        /// <param name="compType">Type of the component</param>
        /// <param name="entityInfo">Breeze EntityInfo</param>
        /// <param name="meta">Metadata for the entity class</param>
        private void FixupComponentRelationships(string propName, ComponentType compType, EntityInfo entityInfo, IClassMetadata meta)
        {
            var compPropNames = compType.PropertyNames;
            var compPropTypes = compType.Subtypes;
            object component = null;
            object[] compValues = null;
            bool isChanged = false;
            for (int j = 0; j < compPropNames.Length; j++)
            {
                var compPropType = compPropTypes[j];
                if (compPropType.IsAssociationType && compPropType.IsEntityType)
                {
                    if (compValues == null)
                    {
                        // get the value of the component's subproperties
                        component = GetPropertyValue(meta, entityInfo.Entity, propName);
                        compValues = compType.GetPropertyValues(component, EntityMode.Poco);
                    }
                    if (compValues[j] == null)
                    {
                        // the related entity is null
                        var relatedEntity = GetRelatedEntity(compPropNames[j], (EntityType)compPropType, entityInfo, meta);
                        if (relatedEntity != null)
                        {
                            compValues[j] = relatedEntity;
                            isChanged = true;
                        }
                    }
                    else if (removeMode)
                    {
                        // remove the relationship
                        compValues[j] = null;
                        isChanged = true;
                    }
                }
            }
            if (isChanged)
            {
                compType.SetPropertyValues(component, compValues, EntityMode.Poco);
            }

        }
示例#28
0
 private string ExistingCustomerSaveGuard(EntityInfo arg)
 {
     var entity = (Customer)arg.Entity;
     var orig = readContext.Customers.SingleOrDefault(e => e.CustomerID == entity.CustomerID);
     return ExistingEntityGuard(orig, entity.CustomerID);
 }
        /// <summary>
        /// Get a related entity based on the value of the foreign key.  Attempts to find the related entity in the
        /// saveMap; if its not found there, it is loaded via the Session (which should create a proxy, not actually load 
        /// the entity from the database).
        /// Related entities are Promoted in the saveOrder according to their state.
        /// </summary>
        /// <param name="propName">Name of the navigation/association property of the entity, e.g. "Customer".  May be null if the property is the entity's identifier.</param>
        /// <param name="propType">Type of the property</param>
        /// <param name="entityInfo">Breeze EntityInfo</param>
        /// <param name="meta">Metadata for the entity class</param>
        /// <returns></returns>
        private object GetRelatedEntity(string propName, EntityType propType, EntityInfo entityInfo, IClassMetadata meta)
        {
            object relatedEntity = null;
            string foreignKeyName = FindForeignKey(propName, meta);
            object id = GetForeignKeyValue(entityInfo, meta, foreignKeyName);

            if (id != null)
            {
                EntityInfo relatedEntityInfo = FindInSaveMap(propType.ReturnedClass, id);

                if (relatedEntityInfo == null) 
                {
                    var state = entityInfo.EntityState;
                    if (state != EntityState.Deleted || !propType.IsNullable)
                    {
                        var relatedEntityName = propType.Name;
                        relatedEntity = session.Load(relatedEntityName, id, LockMode.None);
                    }
                }
                else
                {
                    bool removeReverseRelationship = propType.UseLHSPrimaryKey;
                    AddToGraph(entityInfo, relatedEntityInfo, removeReverseRelationship);
                    relatedEntity = relatedEntityInfo.Entity;
                }
            }
            return relatedEntity;
        }
示例#30
0
 private string ExistingEmployeeSaveGuard(EntityInfo arg)
 {
     var entity = (Employee)arg.Entity;
     var orig = readContext.Employees.SingleOrDefault(e => e.EmployeeID == entity.EmployeeID);
     return ExistingEntityGuard(orig, entity.EmployeeID);
 }
        /// <summary>
        /// Set an association value based on the value of the foreign key.  This updates the property of the entity.
        /// </summary>
        /// <param name="propName">Name of the navigation/association property of the entity, e.g. "Customer".  May be null if the property is the entity's identifier.</param>
        /// <param name="propType">Type of the property</param>
        /// <param name="entityInfo">Breeze EntityInfo</param>
        /// <param name="meta">Metadata for the entity class</param>
        private void FixupRelationship(string propName, EntityType propType, EntityInfo entityInfo, IClassMetadata meta)
        {
            var entity = entityInfo.Entity;
            if (removeMode)
            {
                meta.SetPropertyValue(entity, propName, null, EntityMode.Poco);
                return;
            }
            object relatedEntity = GetPropertyValue(meta, entity, propName);
            if (relatedEntity != null)
            {
                // entities are already connected - still need to add to dependency graph
                EntityInfo relatedEntityInfo = FindInSaveMapByEntity(propType.ReturnedClass, relatedEntity);
                MaybeAddToGraph(entityInfo, relatedEntityInfo, propType);
                return;
            }

            relatedEntity = GetRelatedEntity(propName, propType, entityInfo, meta);

            if (relatedEntity != null)
                meta.SetPropertyValue(entity, propName, relatedEntity, EntityMode.Poco);
        }
示例#32
0
 public TempKeyInfo(EntityInfo entityInfo) {
   _entityInfo = entityInfo;
 }