예제 #1
0
        private void SetValueWithEvents <T>(T property, object newValue, Action <T, Object, Object> action) where T : StructuralProperty
        {
            var oldValue = GetValue(property);

            if (Object.Equals(oldValue, newValue))
            {
                return;
            }

            if (!EntityAspect.OnEntityChanging(EntityAction.PropertyChange))
            {
                return;
            }

            action(property, newValue, oldValue);

            EntityAspect.OnPropertyChanged(this.ParentEntityProperty);

            if (this.IsAttached)
            {
                if (!EntityManager.IsLoadingEntity)
                {
                    if (this.EntityState == EntityState.Unchanged)
                    {
                        EntityAspect.SetModified();
                    }
                }

                if ((EntityManager.ValidationOptions.ValidationApplicability & ValidationApplicability.OnPropertyChange) > 0)
                {
                    ValidateProperty(property, newValue);
                }
            }
        }
예제 #2
0
        public override void Clear()
        {
            var oldErrors = this.ToList();

            base.Clear();
            oldErrors.ForEach(ve => EntityAspect.OnErrorsChanged(ve));
        }
예제 #3
0
        private void SetValueWithEvents <T>(T property, object newValue, Action <T, Object, Object> action) where T : StructuralProperty
        {
            var oldValue = GetValue(property);

            if (Object.Equals(oldValue, newValue))
            {
                return;
            }

            if (!EntityAspect.OnEntityChanging(EntityAction.PropertyChange))
            {
                return;
            }

            action(property, newValue, oldValue);

            EntityAspect.OnPropertyChanged(this.ParentEntityProperty);

            if (this.IsAttached)
            {
                if (!EntityManager.IsLoadingEntity)
                {
                    if (this.EntityState == EntityState.Unchanged)
                    {
                        EntityAspect.SetModified();
                    }
                }

                // TODO: implement this.
                //if (entityManager.validationOptions.validateOnPropertyChange) {
                //    entityAspect._validateProperty(newValue,
                //        { entity: entity, property: property, propertyName: propPath, oldValue: oldValue });
                //}
            }
        }
예제 #4
0
        private void InitializeEntityKey(EntityAspect aspect)
        {
            var ek = aspect.EntityKey;
            // return properties that are = to defaultValues
            var keyProps = aspect.EntityType.KeyProperties;
            var keyPropsWithDefaultValues = keyProps
                                            .Zip(ek.Values, (kp, kv) => kp.DefaultValue == kv ? kp : null)
                                            .Where(kp => kp != null);

            if (keyPropsWithDefaultValues.Any())
            {
                if (aspect.EntityType.AutoGeneratedKeyType != AutoGeneratedKeyType.None)
                {
                    GenerateId(aspect.Entity, keyPropsWithDefaultValues.First(p => p.IsAutoIncrementing));
                }
                else
                {
                    // we will allow attaches of entities where only part of the key is set.
                    if (keyPropsWithDefaultValues.Count() == ek.Values.Length)
                    {
                        throw new Exception("Cannot attach an object of type  (" + aspect.EntityType.Name +
                                            ") to an EntityManager without first setting its key or setting its entityType 'AutoGeneratedKeyType' property to something other than 'None'");
                    }
                }
            }
        }
예제 #5
0
        internal void NotifyStateChange(EntityAspect entityAspect, bool needsSave)
        {
            entityAspect.OnEntityChanged(EntityAction.EntityStateChange);

            if (needsSave)
            {
                SetHasChanges(true);
            }
            else
            {
                // called when rejecting a change or merging an unchanged record.
                // NOTE: this can be slow with lots of entities in the cache.
                if (this._hasChanges)
                {
                    if (this.IsLoadingEntity)
                    {
                        this.HasChangesAction = this.HasChangesAction ?? (() => SetHasChanges(null));
                    }
                    else
                    {
                        SetHasChanges(null);
                    }
                }
            }
        }
예제 #6
0
 /// <summary>
 ///   Triggers the EntityChanged event.
 /// </summary>
 /// <param name="entityAspect">The changed entity's EntityAspect.</param>
 /// <param name="entityAction">The action that caused this change.</param>
 protected virtual void OnEntityChanged(EntityAspect entityAspect, EntityAction entityAction)
 {
     if (EntityChanged != null)
     {
         EntityChanged(this, new EntityChangedEventArgs(entityAspect, entityAction));
     }
 }
예제 #7
0
 private void RetainDeletedEntityKeys(IEnumerable <object> syncEntities)
 {
     _deletedEntityKeys = syncEntities
                          .Where(e => EntityAspect.Wrap(e).EntityState.IsDeleted())
                          .Select(e => EntityAspect.Wrap(e).EntityKey)
                          .ToList();
 }
예제 #8
0
        SaveResult InsertTestDataBaseLineIntoDb(PersistManager <BloggerContextPg> uut)
        {
            var blog = new Blog
            {
                Id  = -1,
                Url = "www.example.com"
            };

            var blogEntityAspect = new EntityAspect(blog, EntityState.Added);

            var post = new Post
            {
                BlogId    = -1,
                Content   = "I am content",
                Id        = -2,
                Title     = "this is the title",
                CreatedAt = Instant.FromUtc(2002, 10, 8, 6, 4)
            };

            var postEntityAspect = new EntityAspect(post, EntityState.Added);

            var saveBundle0 = new ClientSaveBundle();

            saveBundle0.AddEntity(blogEntityAspect);
            saveBundle0.AddEntity(postEntityAspect);

            var parsedSaveBundle = JObject.Parse(saveBundle0.ToJson());

            var saveResult = uut.SaveChanges(parsedSaveBundle.ToString());

            return(saveResult);
        }
예제 #9
0
        internal void NotifyStateChange(EntityAspect entityAspect, bool needsSave)
        {
            OnEntityChanged(entityAspect.Entity, EntityAction.EntityStateChange);

            if (needsSave)
            {
                if (!this._hasChanges)
                {
                    this._hasChanges = true;
                    OnHasChangesChanged();
                }
            }
            else
            {
                // called when rejecting a change or merging an unchanged record.
                if (this._hasChanges)
                {
                    // NOTE: this can be slow with lots of entities in the cache.
                    this._hasChanges = this.HasChangesCore(null);
                    if (!this._hasChanges)
                    {
                        OnHasChangesChanged();
                    }
                }
            }
        }
예제 #10
0
        private EntityAspect AttachEntityAspect(EntityAspect entityAspect, EntityState entityState)
        {
            var group = GetEntityGroup(entityAspect.EntityType.ClrType);

            group.AttachEntityAspect(entityAspect, entityState);
            entityAspect.LinkRelatedEntities();
            return(entityAspect);
        }
예제 #11
0
 public override void Add(ValidationError item)
 {
     if (!this.Contains(item))
     {
         base.Add(item);
         EntityAspect.OnErrorsChanged(item);
     }
 }
예제 #12
0
        public override void OnSaving(TempHireEntities source, EntitySavingEventArgs args)
        {
            // Add necessary aggregate root object to the save list for validation and concurrency check
            List <EntityAspect> rootEas = args.Entities.OfType <IHasRoot>()
                                          .Select(e => EntityAspect.Wrap(e.Root))
                                          .Distinct()
                                          .Where(ea => ea != null && !ea.IsChanged && !ea.IsNullOrPendingEntity)
                                          .ToList();

            rootEas.ForEach(ea => ea.SetModified());
            rootEas.ForEach(ea => args.Entities.Add(ea.Entity));
        }
예제 #13
0
 public override bool Remove(ValidationError item)
 {
     if (base.Remove(item))
     {
         EntityAspect.OnErrorsChanged(item);
         return(true);
     }
     else
     {
         return(false);
     }
 }
예제 #14
0
        private IEnumerable <String> GetTempNavPropNames(EntityAspect entityAspect)
        {
            var npNames = entityAspect.EntityType.NavigationProperties.Where(np => {
                if (!np.IsScalar)
                {
                    return(false);
                }
                var val = (IEntity)entityAspect.GetRawValue(np.Name);
                return(val != null && val.EntityAspect.HasTemporaryKey);
            }).Select(np => np.Name);

            return(npNames);
        }
예제 #15
0
        private JNode ExportEntityAspectInfo(EntityAspect entityAspect)
        {
            var jn = new JNode();
            var es = entityAspect.EntityState;

            jn.AddEnum("entityState", entityAspect.EntityState);
            jn.AddArray("tempNavPropNames", GetTempNavPropNames(entityAspect));
            if (es.IsModified() || es.IsDeleted())
            {
                jn.AddMap("originalValuesMap", entityAspect._originalValuesMap);
            }
            return(jn);
        }
예제 #16
0
        public void ClientSaveBundle_EntityAspect_ChangeValue_Test()
        {
            var originalUrl = "www.oldUrl.com";
            var newUrl      = "www.newUrl.com";
            var blog        = new Blog {
                Url = originalUrl
            };
            var blogEntityAspect = new EntityAspect(blog, EntityState.Added);

            blogEntityAspect.ChangeValue("Url", newUrl);
            blog.Url.Should().Be(newUrl);
            blogEntityAspect.OriginalValuesMap.Should()
            .Contain(KeyValuePair.Create("Url", originalUrl as object));
        }
예제 #17
0
        private void RaiseDataChangedEvent(IEnumerable <object> savedEntities, IEnumerable <EntityKey> deletedEntityKeys)
        {
            var entityKeys = savedEntities
                             .Select(e => EntityAspect.Wrap(e).EntityKey)
                             .Concat(deletedEntityKeys)
                             .ToList();

            if (!entityKeys.Any())
            {
                return;
            }

            OnDataChanged(entityKeys);
        }
예제 #18
0
        public override bool RemoveKey(string key)
        {
            var removedError = this[key];

            if (removedError != null)
            {
                base.RemoveKey(key);
                EntityAspect.OnErrorsChanged(removedError);
                return(true);
            }
            else
            {
                return(false);
            }
        }
예제 #19
0
 internal void CheckStateChange(EntityAspect entityAspect, bool wasUnchanged, bool isUnchanged)
 {
     if (wasUnchanged)
     {
         if (!isUnchanged)
         {
             this.NotifyStateChange(entityAspect, true);
         }
     }
     else
     {
         if (isUnchanged)
         {
             this.NotifyStateChange(entityAspect, false);
         }
     }
 }
예제 #20
0
        public override bool ShouldImportEntity(object entity)
        {
            // Only import if the importing EntityManager holds a copy of the entity or its root aggregate in its cache
            if (EntityManager.FindEntity(EntityAspect.Wrap(entity).EntityKey) != null)
            {
                return(true);
            }

            var hasRoot = entity as IHasRoot;

            if (hasRoot != null)
            {
                return(EntityManager.FindEntity(EntityAspect.Wrap(hasRoot.Root).EntityKey) != null);
            }

            return(false);
        }
예제 #21
0
 private JNode BuildEntityAspectNode(EntityAspect entityAspect) {
   var nc = MetadataStore.Instance.NamingConvention;
   var jn = new JNode();
   var entityType = entityAspect.EntityType;
     
   jn.AddPrimitive("entityTypeName", entityType.Name);
   jn.AddEnum("entityState", entityAspect.EntityState);
   jn.AddPrimitive("defaultResourceName", entityType.DefaultResourceName);
   jn.AddJNode("originalValuesMap", BuildOriginalValuesMapNode(entityAspect, nc));
   var agkType = entityType.AutoGeneratedKeyType;
   if (agkType != AutoGeneratedKeyType.None) {
     var agkNode = new JNode();
     agkNode.AddPrimitive("propertyName", entityType.KeyProperties[0].Name);
     agkNode.AddEnum("autoGeneratedKeyType", agkType);
     jn.AddJNode("autoGeneratedKey", agkNode);
   }
   return jn;
 }
예제 #22
0
 private void OnSaved(object sender, EntitySavedEventArgs e)
 {
     try
     {
         if (!e.HasError)
         {
             var exportEntities = e.Entities
                                  .Where(entity => SyncInterceptor.ShouldExportEntity(entity) &&
                                         !_deletedEntityKeys
                                         .Contains(EntityAspect.Wrap(entity).EntityKey))
                                  .ToList();
             PublishEntities(exportEntities);
         }
         _deletedEntityKeys = null;
     }
     finally
     {
         IsSaving = false;
     }
 }
예제 #23
0
        public void ClientSaveBundle_EntityAndEntityAspectToJson_Test()
        {
            var blog = new Blog {
                Url = "www.example.com", CreatedAt = Instant.FromUtc(2002, 10, 8, 6, 4)
            };
            var blogEntityAspect = new EntityAspect(blog, EntityState.Added);

            {
                var uut = new ClientSaveBundle(pascalCase: false);
                var entityWithAspectAsJson = uut.EntityAndEntityAspectToJObject(blog, blogEntityAspect).ToString();
                entityWithAspectAsJson.Should().Contain("\"url\": \"www.example.com\",");
                Console.WriteLine(entityWithAspectAsJson);
            }

            {
                var uut = new ClientSaveBundle(pascalCase: true);
                var entityWithAspectAsJson = uut.EntityAndEntityAspectToJObject(blog, blogEntityAspect).ToString();
                entityWithAspectAsJson.Should().Contain("\"Url\": \"www.example.com\",");
            }
        }
예제 #24
0
        private JNode BuildEntityAspectNode(EntityAspect entityAspect)
        {
            var nc         = entityAspect.EntityManager.MetadataStore.NamingConvention;
            var jn         = new JNode();
            var entityType = entityAspect.EntityType;

            jn.AddPrimitive("entityTypeName", entityType.NameOnServer);
            jn.AddEnum("entityState", entityAspect.EntityState);
            jn.AddPrimitive("defaultResourceName", entityType.DefaultResourceName);
            jn.AddJNode("originalValuesMap", BuildOriginalValuesMapNode(entityAspect, nc));
            var agkType = entityType.AutoGeneratedKeyType;

            if (agkType != AutoGeneratedKeyType.None)
            {
                var agkNode = new JNode();
                agkNode.AddPrimitive("propertyName", entityType.KeyProperties[0].Name);
                agkNode.AddEnum("autoGeneratedKeyType", agkType);
                jn.AddJNode("autoGeneratedKey", agkNode);
            }
            return(jn);
        }
예제 #25
0
        protected override bool ValidateSave()
        {
            base.ValidateSave();

            // Create a sandbox to do the validation in.
            var em = new EntityManager(EntityManager);

            em.CacheStateManager.RestoreCacheState(EntityManager.CacheStateManager.GetCacheState());

            // Find all entities supporting custom validation
            var entities =
                em.FindEntities(EntityState.AllButDetached).OfType <EntityBase>().ToList();

            foreach (var e in entities)
            {
                var entityAspect = EntityAspect.Wrap(e);
                if (entityAspect.EntityState.IsDeletedOrDetached())
                {
                    continue;
                }

                var validationErrors = new VerifierResultCollection();
                e.Validate(validationErrors);

                validationErrors =
                    new VerifierResultCollection(entityAspect.ValidationErrors.Concat(validationErrors.Errors));
                validationErrors.Where(vr => !entityAspect.ValidationErrors.Contains(vr))
                .ForEach(entityAspect.ValidationErrors.Add);

                if (validationErrors.HasErrors)
                {
                    throw new EntityServerException(validationErrors.Select(v => v.Message).ToAggregateString("\n"),
                                                    null,
                                                    PersistenceOperation.Save, PersistenceFailure.Validation);
                }
            }

            return(true);
        }
예제 #26
0
        /// <summary>
        /// Insures that a temporary pk is set if necessary
        /// </summary>
        /// <param name="aspect"></param>
        internal void UpdatePkIfNeeded(EntityAspect aspect)
        {
            if (KeyGenerator == null)
            {
                return;
            }
            var keyProperties = aspect.EntityType.KeyProperties;

            foreach (var aProperty in keyProperties)
            {
                var val       = aspect.GetValue(aProperty.Name);
                var aUniqueId = new UniqueId(aProperty, val);

                // determine if a temp pk is needed.
                if (aProperty.IsAutoIncrementing)
                {
                    if (!KeyGenerator.IsTempId(aUniqueId))
                    {
                        // generate an id if it wasn't already generated
                        aUniqueId = GenerateId(aspect.Entity, aProperty);
                    }
                    AddToTempIds(aUniqueId);
                }
                else if (aProperty.DefaultValue == val)
                {
                    // do not call GenerateId unless the developer is explicit or the key is autoincrementing.
                }
                else
                {
                    // this occurs if GenerateId was called before Attach - it won't have been added to tempIds in this case.
                    if (KeyGenerator.IsTempId(aUniqueId))
                    {
                        AddToTempIds(aUniqueId);
                    }
                }
            }
        }
예제 #27
0
        private void Validate(EntitySavingEventArgs args)
        {
            var allValidationErrors = new VerifierResultCollection();

            foreach (var entity in args.Entities)
            {
                var entityAspect = EntityAspect.Wrap(entity);
                if (entityAspect.EntityState.IsDeletedOrDetached())
                {
                    continue;
                }

                var validationErrors = Manager.VerifierEngine.Execute(entity);
                foreach (var d in _configuration.Delegates ?? new EntityManagerDelegate <T> [0])
                {
                    d.Validate(entity, validationErrors);
                }
                // Extract only validation errors
                validationErrors = validationErrors.Errors;

                validationErrors.Where(vr => !entityAspect.ValidationErrors.Contains(vr))
                .ForEach(entityAspect.ValidationErrors.Add);

                validationErrors.ForEach(allValidationErrors.Add);
            }

            if (allValidationErrors.HasErrors)
            {
                if (!ValidationErrorNotifiers.Any())
                {
                    throw new ValidationException(allValidationErrors.Select(v => v.Message).ToAggregateString("\n"));
                }

                ValidationErrorNotifiers.ForEach(s => s.OnValidationError(allValidationErrors));
                args.Cancel = true;
            }
        }
예제 #28
0
        internal void MarkTempIdAsMapped(EntityAspect aspect, bool isMapped)
        {
            var keyProperties = aspect.EntityType.KeyProperties;

            foreach (var aProperty in keyProperties)
            {
                UniqueId aUniqueId = new UniqueId(aProperty, aspect.GetValue(aProperty.Name));
                if (isMapped)
                {
                    TempIds.Remove(aUniqueId);
                }
                else
                {
                    if (KeyGenerator == null)
                    {
                        return;
                    }
                    if (KeyGenerator.IsTempId(aUniqueId))
                    {
                        TempIds.Add(aUniqueId);
                    }
                }
            }
        }
예제 #29
0
 private void ParseObject(JsonContext jsonContext, EntityAspect targetAspect) {
   // backingStore will be null if not allowed to overwrite the entity.
   var backingStore = (targetAspect == null) ? null : targetAspect.BackingStore;
   var dict = (IDictionary<String, JToken>) jsonContext.JObject;
   var structuralType = jsonContext.StructuralType;
   dict.ForEach(kvp => {
     var key = kvp.Key;
     var prop = structuralType.GetProperty(key);
     if (prop != null) {         
       if (prop.IsDataProperty) {
         if (backingStore != null) {
           var dp = (DataProperty)prop;
           if (dp.IsComplexProperty) {
             var newCo = (IComplexObject) kvp.Value.ToObject(dp.ClrType);
             var co = (IComplexObject)backingStore[key];
             var coBacking = co.ComplexAspect.BackingStore;
             newCo.ComplexAspect.BackingStore.ForEach(kvp2 => {
               coBacking[kvp2.Key] = kvp2.Value;
             });
           } else {
             backingStore[key] = kvp.Value.ToObject(dp.ClrType);
           }
         }
       } else {
         // prop is a ComplexObject
         var np = (NavigationProperty)prop;
         
         if (kvp.Value.HasValues) {
           JsonContext newContext;
           if (np.IsScalar) {
             var nestedOb = (JObject)kvp.Value;
             newContext = new JsonContext() { JObject = nestedOb, ObjectType = prop.ClrType, Serializer = jsonContext.Serializer }; 
             var entity = (IEntity)CreateAndPopulate(newContext);
             if (backingStore != null) backingStore[key] = entity;
           } else {
             var nestedArray = (JArray)kvp.Value;
             var navSet = (INavigationSet) TypeFns.CreateGenericInstance(typeof(NavigationSet<>), prop.ClrType);
             
             nestedArray.Cast<JObject>().ForEach(jo => {
               newContext = new JsonContext() { JObject=jo, ObjectType = prop.ClrType, Serializer = jsonContext.Serializer };
               var entity = (IEntity)CreateAndPopulate(newContext);
               navSet.Add(entity);
             });
             // add to existing nav set if there is one otherwise just set it. 
             object tmp;
             if (backingStore.TryGetValue(key, out tmp)) {
               var backingNavSet = (INavigationSet) tmp;
               navSet.Cast<IEntity>().ForEach(e => backingNavSet.Add(e));
             } else {
               navSet.NavigationProperty = np;
               navSet.ParentEntity = targetAspect.Entity;
               backingStore[key] = navSet;
             }
           }
         } else {
           // do nothing
           //if (!np.IsScalar) {
           //  return TypeFns.ConstructGenericInstance(typeof(NavigationSet<>), prop.ClrType);
           //} else {
           //  return null;
           //}
         }
       }
     } else {
       if (backingStore != null) backingStore[key] = kvp.Value.ToObject<Object>();
     }
   });
   
 }
예제 #30
0
 private void ParseObject(NodeContext nodeContext, EntityAspect targetAspect) {
   // backingStore will be null if not allowed to overwrite the entity.
   var backingStore = (targetAspect == null) ? null : targetAspect.BackingStore;
   var dict = (IDictionary<String, JToken>) nodeContext.Node;
   var structuralType = nodeContext.StructuralType;
   // needs to be the current namingConvention
   var nc = _mappingContext.EntityManager.MetadataStore.NamingConvention;
   dict.ForEach(kvp => {
     var key = nc.ServerPropertyNameToClient(kvp.Key, structuralType);
     var prop = structuralType.GetProperty(key);
     if (prop != null) {         
       if (prop.IsDataProperty) {
         if (backingStore != null) {
           var dp = (DataProperty)prop;
           if (dp.IsComplexProperty) {
             var newCo = (IComplexObject) kvp.Value.ToObject(dp.ClrType);
             var co = (IComplexObject)backingStore[key];
             var coBacking = co.ComplexAspect.BackingStore;
             newCo.ComplexAspect.BackingStore.ForEach(kvp2 => {
               coBacking[kvp2.Key] = kvp2.Value;
             });
           } else {
             var val = kvp.Value;
             if (val.Type == JTokenType.Null && dp.ClrType != typeof(String) && !TypeFns.IsNullableType(dp.ClrType)) {
               // this can only happen if the client is nonnullable but the server is nullable.
               backingStore[key] = dp.DefaultValue;
             } else if (dp.IsEnumType || (dp.DataType.ClrType == typeof (TimeSpan))) {
               backingStore[key] = val.ToObject(dp.ClrType, _customSerializer);
             } else {
               backingStore[key] = val.ToObject(dp.ClrType);
             }
           }
         }
       } else {
         // prop is a ComplexObject
         var np = (NavigationProperty)prop;
         
         if (kvp.Value.HasValues) {
           NodeContext newContext;
           if (np.IsScalar) {
             var nestedOb = (JObject)kvp.Value;
             newContext = new NodeContext() { Node = nestedOb, ObjectType = prop.ClrType, StructuralProperty = np}; 
             var entity = (IEntity)CreateAndPopulate(newContext);
             if (backingStore != null) backingStore[key] = entity;
           } else {
             var nestedArray = (JArray)kvp.Value;
             var navSet = (INavigationSet) TypeFns.CreateGenericInstance(typeof(NavigationSet<>), prop.ClrType);
             
             nestedArray.Cast<JObject>().ForEach(jo => {
               newContext = new NodeContext() { Node=jo, ObjectType = prop.ClrType, StructuralProperty = np};
               var entity = (IEntity)CreateAndPopulate(newContext);
               navSet.Add(entity);
             });
             // add to existing nav set if there is one otherwise just set it. 
             object tmp;
             if (backingStore.TryGetValue(key, out tmp)) {
               var backingNavSet = (INavigationSet) tmp;
               navSet.Cast<IEntity>().ForEach(e => backingNavSet.Add(e));
             } else {
               navSet.NavigationProperty = np;
               navSet.ParentEntity = targetAspect.Entity;
               backingStore[key] = navSet;
             }
           }
         } else {
           // do nothing
           //if (!np.IsScalar) {
           //  return TypeFns.ConstructGenericInstance(typeof(NavigationSet<>), prop.ClrType);
           //} else {
           //  return null;
           //}
         }
       }
     } else {
       if (backingStore != null) backingStore[key] = kvp.Value.ToObject<Object>();
     }
   });
   
 }
예제 #31
0
 IEnumerable INotifyDataErrorInfo.GetErrors(string propertyName)
 {
     // parent EntityAspect has all of the errors.
     return(EntityAspect.GetValidationErrors(this.GetPropertyPath(propertyName)));
 }
예제 #32
0
        private void ParseObject(NodeContext nodeContext, EntityAspect targetAspect)
        {
            // backingStore will be null if not allowed to overwrite the entity.
            var backingStore   = (targetAspect == null) ? null : targetAspect.BackingStore;
            var dict           = (IDictionary <String, JToken>)nodeContext.Node;
            var structuralType = nodeContext.StructuralType;
            // needs to be the current namingConvention
            var nc = _mappingContext.EntityManager.MetadataStore.NamingConvention;

            dict.ForEach(kvp => {
                var key  = nc.ServerPropertyNameToClient(kvp.Key, structuralType);
                var prop = structuralType.GetProperty(key);
                if (prop != null)
                {
                    if (prop.IsDataProperty)
                    {
                        if (backingStore != null)
                        {
                            var dp = (DataProperty)prop;
                            if (dp.IsComplexProperty)
                            {
                                var newCo     = (IComplexObject)kvp.Value.ToObject(dp.ClrType);
                                var co        = (IComplexObject)backingStore[key];
                                var coBacking = co.ComplexAspect.BackingStore;
                                newCo.ComplexAspect.BackingStore.ForEach(kvp2 => {
                                    coBacking[kvp2.Key] = kvp2.Value;
                                });
                            }
                            else
                            {
                                var val = kvp.Value;
                                if (val.Type == JTokenType.Null && dp.ClrType != typeof(String) && !TypeFns.IsNullableType(dp.ClrType))
                                {
                                    // this can only happen if the client is nonnullable but the server is nullable.
                                    backingStore[key] = dp.DefaultValue;
                                }
                                else if (dp.IsEnumType || (dp.DataType.ClrType == typeof(TimeSpan)))
                                {
                                    backingStore[key] = val.ToObject(dp.ClrType, _customSerializer);
                                }
                                else
                                {
                                    backingStore[key] = val.ToObject(dp.ClrType);
                                }
                            }
                        }
                    }
                    else
                    {
                        // prop is a ComplexObject
                        var np = (NavigationProperty)prop;

                        if (kvp.Value.HasValues)
                        {
                            NodeContext newContext;
                            if (np.IsScalar)
                            {
                                var nestedOb = (JObject)kvp.Value;
                                newContext   = new NodeContext()
                                {
                                    Node = nestedOb, ObjectType = prop.ClrType, StructuralProperty = np
                                };
                                var entity = (IEntity)CreateAndPopulate(newContext);
                                if (backingStore != null)
                                {
                                    backingStore[key] = entity;
                                }
                            }
                            else
                            {
                                var nestedArray = (JArray)kvp.Value;
                                var navSet      = (INavigationSet)TypeFns.CreateGenericInstance(typeof(NavigationSet <>), prop.ClrType);

                                nestedArray.Cast <JObject>().ForEach(jo => {
                                    newContext = new NodeContext()
                                    {
                                        Node = jo, ObjectType = prop.ClrType, StructuralProperty = np
                                    };
                                    var entity = (IEntity)CreateAndPopulate(newContext);
                                    navSet.Add(entity);
                                });
                                // add to existing nav set if there is one otherwise just set it.
                                object tmp;
                                if (backingStore.TryGetValue(key, out tmp))
                                {
                                    var backingNavSet = (INavigationSet)tmp;
                                    navSet.Cast <IEntity>().ForEach(e => backingNavSet.Add(e));
                                }
                                else
                                {
                                    navSet.NavigationProperty = np;
                                    navSet.ParentEntity       = targetAspect.Entity;
                                    backingStore[key]         = navSet;
                                }
                            }
                        }
                        else
                        {
                            // do nothing
                            //if (!np.IsScalar) {
                            //  return TypeFns.ConstructGenericInstance(typeof(NavigationSet<>), prop.ClrType);
                            //} else {
                            //  return null;
                            //}
                        }
                    }
                }
                else
                {
                    if (backingStore != null)
                    {
                        backingStore[key] = kvp.Value.ToObject <Object>();
                    }
                }
            });
        }
예제 #33
0
 public ValidationErrorCollection(EntityAspect entityAspect)
 {
     EntityAspect = entityAspect;
 }
예제 #34
0
 public EntityFacts(object entity)
 {
     _entityAspect = EntityAspect.Wrap(entity);
 }