Beispiel #1
0
        public virtual bool Copy(object srcEntity, EntityEntry destEntry)
        {
            bool modified = false;

            foreach (PropertyEntry property in destEntry.Properties)
            {
                if (!(property.Metadata.FieldInfo == null ||
                      property.Metadata.IsPrimaryKey() ||
                      property.Metadata.IsForeignKey() ||
                      property.Metadata.BeforeSaveBehavior == PropertySaveBehavior.Ignore || //IsStoreGeneratedAlways ||
                      property.Metadata.AfterSaveBehavior == PropertySaveBehavior.Throw ||   //IsReadOnlyAfterSave ||
                      property.Metadata.IsIgnored()))
                {
                    IClrPropertyGetter getter   = property.Metadata.GetGetter();
                    object             srcValue = getter.GetClrValue(srcEntity);
                    if (srcValue != property.CurrentValue)
                    {
                        if (!_eventManager.OnPropertyChanging(property, srcValue).Cancel)
                        {
                            property.CurrentValue = srcValue;
                            _eventManager.OnPropertyChanged(property, srcValue);
                            modified = true;
                        }
                    }
                }
            }
            return(modified);
        }
Beispiel #2
0
 /// <summary>
 ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
 ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
 ///     any release. You should only use it directly in your code with extreme caution and knowing that
 ///     doing so can result in application failures when updating to a new Entity Framework Core release.
 /// </summary>
 public TypeMappedPropertyRelationalParameter(
     string invariantName,
     string name,
     RelationalTypeMapping relationalTypeMapping,
     IProperty property)
     : base(invariantName, name, relationalTypeMapping, property.IsNullable)
 {
     _clrPropertyGetter = property.GetGetter();
 }
 /// <summary>
 ///     This API supports the Entity Framework Core infrastructure and is not intended to be used 
 ///     directly from your code. This API may change or be removed in future releases.
 /// </summary>
 public TypeMappedPropertyRelationalParameter(
     [NotNull] string invariantName,
     [NotNull] string name,
     [NotNull] RelationalTypeMapping relationalTypeMapping,
     [NotNull] IProperty property)
     : base(invariantName, name, relationalTypeMapping, property.IsNullable)
 {
     _clrPropertyGetter = property.GetGetter();
 }
Beispiel #4
0
        private static T GetValueFromEntity <T>(IClrPropertyGetter clrPropertyGetter, object entity)
        {
            if (entity == null)
            {
                return(default(T));
            }

            return((T)clrPropertyGetter.GetClrValue(entity));
        }
Beispiel #5
0
        private static void TryAddArgumentFromSource(
            ResolveFieldContext resolveFieldContext,
            string argument,
            IClrPropertyGetter getter)
        {
            if (resolveFieldContext.Arguments == null)
            {
                resolveFieldContext.Arguments = new Dictionary <string, object>();
            }

            var value = getter.GetClrValue(resolveFieldContext.Source);

            Debug.Assert(value != null);

            resolveFieldContext.Arguments[argument] = value;
        }
        /// <inheritdoc />
        public override void IncludeCollection <TEntity, TRelated, TElement>(
            int includeId,
            INavigation navigation,
            INavigation inverseNavigation,
            IEntityType targetEntityType,
            IClrCollectionAccessor clrCollectionAccessor,
            IClrPropertySetter inverseClrPropertySetter,
            bool tracking,
            TEntity entity,
            Func <IEnumerable <TRelated> > relatedEntitiesFactory,
            Func <TEntity, TRelated, bool> joinPredicate)
        {
            Check.NotNull(clrCollectionAccessor, nameof(clrCollectionAccessor));
            Check.NotNull(inverseNavigation, nameof(inverseNavigation));
            Check.NotNull(inverseClrPropertySetter, nameof(inverseClrPropertySetter));

            ICollection <TRelated> collection = (ICollection <TRelated>)clrCollectionAccessor
                                                .GetOrCreate(entity);

            IClrPropertyGetter primaryKeyPropertyGetter = inverseNavigation
                                                          .DeclaringEntityType
                                                          .FindPrimaryKey()
                                                          .Properties
                                                          .Single()
                                                          .GetGetter();

            IEnumerable <(TRelated, TRelated)> relatedEntities = relatedEntitiesFactory()
                                                                 .Join(collection,
                                                                       related => primaryKeyPropertyGetter.GetClrValue(related),
                                                                       related => primaryKeyPropertyGetter.GetClrValue(related),
                                                                       (related, original) => (related, original))
                                                                 .ToList();

            foreach ((TRelated related, TRelated original) in relatedEntities)
            {
                collection.Remove(original);
                collection.Add(related);
                inverseClrPropertySetter.SetClrValue(related, entity);
            }
        }
 public SimpleKeyGetter(IClrPropertyGetter keyGetter)
 {
     _keyGetter = keyGetter;
 }
 public ForeignKeyGetter(IClrPropertyGetter entityGetter, IEnumerable <IClrPropertyGetter> keyGetters)
 {
     _entityGetter = entityGetter;
     _keyGetters   = keyGetters;
 }
Beispiel #9
0
        protected virtual EntityEntry Merge(object detached, object persisted, NavigationEntry parentNavigation, HashSet <object> visited)
        {
            _eventManager.OnEntityMerging(detached, persisted, parentNavigation);

            EntityEntry persistedEntry = _entryServices.FindEntry(persisted) ?? _dbContext.Entry(persisted);

            visited.Add(persistedEntry.Entity);

            bool modified = Copy(detached, persistedEntry);

            foreach (NavigationEntry navigationEntry in persistedEntry.Navigations)
            {
                bool owned      = navigationEntry.Metadata.IsOwned();
                bool associated = navigationEntry.Metadata.IsAssociated();

                if (!(associated || owned))
                {
                    continue;
                }

                IEntityType        navType       = navigationEntry.Metadata.GetTargetType();
                IClrPropertyGetter getter        = navigationEntry.Metadata.GetGetter();
                object             detachedValue = getter.GetClrValue(detached);

                IEntityServices entityServices = _entityServicesFactory.GetEntityServices(navType);

                if (navigationEntry.Metadata.IsCollection())
                {
                    // a mutable list to store the result.
                    IList mergedList = Activator.CreateInstance(typeof(List <>).MakeGenericType(navType.ClrType)) as IList;

                    // create hash table for O(N) merge.
                    Dictionary <KeyValue, object> dbTable = entityServices.CreateTable((IEnumerable)navigationEntry.CurrentValue);

                    if (detachedValue != null)
                    {
                        foreach (var detachedItem in (IEnumerable)detachedValue)
                        {
                            object   persistedItem;
                            KeyValue entityKey = entityServices.GetKeyValue(detachedItem);

                            if (dbTable.TryGetValue(entityKey, out persistedItem))
                            {
                                mergedList.Add(owned
                                    ? Merge(detachedItem, persistedItem, navigationEntry, visited).Entity
                                    : persistedItem);

                                dbTable.Remove(entityKey); // remove it from the table, to avoid deletion.
                            }
                            else
                            {
                                mergedList.Add(owned ? Add(detachedItem, navigationEntry, visited).Entity
                                                     : Attach(detachedItem, navigationEntry).Entity);
                            }
                        }
                    }

                    // the rest of the items in the dbTable should be removed.
                    foreach (var dbItem in dbTable)
                    {
                        Delete(dbItem.Value, navigationEntry, visited);
                    }

                    // let EF do the rest of the work.
                    navigationEntry.CurrentValue = mergedList;
                }
                else
                {
                    if (visited.Contains(navigationEntry.CurrentValue))
                    {
                        continue;
                    }

                    if (entityServices.Equal(detachedValue, navigationEntry.CurrentValue))
                    {
                        // merge owned references and do nothing for associated references.
                        if (owned)
                        {
                            navigationEntry.CurrentValue = Merge(detachedValue, navigationEntry.CurrentValue, navigationEntry, visited).Entity;
                        }
                    }
                    else
                    {
                        if (navigationEntry.CurrentValue != null)
                        {
                            if (owned)
                            {
                                Delete(navigationEntry.CurrentValue, navigationEntry, visited);
                            }
                        }

                        if (detachedValue != null)
                        {
                            navigationEntry.CurrentValue = owned ?
                                                           Add(detachedValue, navigationEntry, visited).Entity :
                                                           Attach(detachedValue, navigationEntry).Entity;
                        }
                        else
                        {
                            // fix: if we use lazy loading we can delete correct value
                            // for example: [FK] ItemId -> Item (is null)
                            // ItemId = 1 (from RESTfull for example), Item = null
                            var fk   = navigationEntry.Metadata.ForeignKey?.Properties?.SingleOrDefault();
                            var data = fk?.GetGetter().GetClrValue(detached);
                            if (data != null && data.GetType().IsPrimitive&& !data.GetType().IsDefaultValue(data))
                            {
                                continue;
                            }

                            navigationEntry.CurrentValue = null;
                        }
                    }
                }
            }

            return(_eventManager.OnEntityMerged(detached, persistedEntry, modified, parentNavigation).EntityEntry);
        }
Beispiel #10
0
        /// <inheritdoc />
        public override void IncludeCollection <TEntity, TRelated, TElement>(
            int includeId,
            INavigation navigation,
            INavigation inverseNavigation,
            IEntityType targetEntityType,
            IClrCollectionAccessor clrCollectionAccessor,
            IClrPropertySetter inverseClrPropertySetter,
            bool tracking,
            TEntity entity,
            Func <IEnumerable <TRelated> > relatedEntitiesFactory,
            Func <TEntity, TRelated, bool> joinPredicate)
        {
            Check.NotNull(clrCollectionAccessor, nameof(clrCollectionAccessor));
            Check.NotNull(inverseNavigation, nameof(inverseNavigation));
            Check.NotNull(inverseClrPropertySetter, nameof(inverseClrPropertySetter));

            ICollection <TRelated> collection = (ICollection <TRelated>)clrCollectionAccessor
                                                .GetOrCreate(entity);

            IClrPropertyGetter primaryKeyPropertyGetter = navigation
                                                          .GetTargetType()
                                                          .FindPrimaryKey()
                                                          .Properties
                                                          .Single()
                                                          .GetGetter();

            IDictionary <object, TRelated> replacementMap = relatedEntitiesFactory()
                                                            .ToDictionary(
                related => primaryKeyPropertyGetter.GetClrValue(related));

            IEnumerable <object> newCollectionItems = collection
                                                      .Select(original =>
                                                              replacementMap.TryGetValue(
                                                                  primaryKeyPropertyGetter.GetClrValue(original),
                                                                  out TRelated related)
                        ? related
                        : original)
                                                      .Cast <object>()
                                                      .ToList();

            collection.Clear();

            foreach (TRelated item in newCollectionItems)
            {
                inverseClrPropertySetter.SetClrValue(item, entity);

                if (tracking)
                {
                    InternalEntityEntry originalEntry = _stateManager.TryGetEntry(item);
                    if (originalEntry != null)
                    {
                        _stateManager.StopTracking(originalEntry);
                    }

                    base.StartTracking(
                        LoadEntity(
                            item,
                            targetEntityType,
                            entity,
                            inverseNavigation),
                        targetEntityType);
                }
            }
        }
Beispiel #11
0
        protected virtual EntityEntry Merge(object detached, object persisted, NavigationEntry parentNavigation, HashSet <object> visited)
        {
            var args = _eventManager.OnEntityMerging(detached, persisted, parentNavigation);

            EntityEntry persistedEntry = _entryServices.FindEntry(persisted);

            if (persistedEntry == null)
            {
                persistedEntry = _dbContext.Entry(persisted);
            }

            visited.Add(persistedEntry.Entity);

            bool modified = Copy(detached, persistedEntry);

            foreach (NavigationEntry navigationEntry in persistedEntry.Navigations)
            {
                bool owned      = navigationEntry.Metadata.IsOwned();
                bool associated = navigationEntry.Metadata.IsAssociated();

                if (!(associated || owned))
                {
                    continue;
                }

                IEntityType        navType       = navigationEntry.Metadata.GetTargetType();
                IClrPropertyGetter getter        = navigationEntry.Metadata.GetGetter();
                object             detachedValue = getter.GetClrValue(detached);

                IEntityServices entityServices = _entityServicesFactory.GetEntityServices(navType);

                if (navigationEntry.Metadata.IsCollection())
                {
                    // a mutable list to store the result.
                    IList mergedList = Activator.CreateInstance(typeof(List <>).MakeGenericType(navType.ClrType)) as IList;

                    // create hash table for O(N) merge.
                    Dictionary <KeyValue, object> dbTable = entityServices.CreateTable((IEnumerable)navigationEntry.CurrentValue);

                    if (detachedValue != null)
                    {
                        foreach (object detachedItem in (IEnumerable)detachedValue)
                        {
                            object   persistedItem;
                            KeyValue entityKey = entityServices.GetKeyValue(detachedItem);
                            if (dbTable.TryGetValue(entityKey, out persistedItem))
                            {
                                if (owned)
                                {
                                    mergedList.Add(Merge(detachedItem, persistedItem, navigationEntry, visited).Entity);
                                }
                                else
                                {
                                    mergedList.Add(persistedItem);
                                }

                                dbTable.Remove(entityKey); // remove it from the table, to avoid deletion.
                            }
                            else
                            {
                                mergedList.Add(owned ? Add(detachedItem, navigationEntry, visited).Entity
                                                     : Attach(detachedItem, navigationEntry).Entity);
                            }
                        }
                    }

                    // the rest of the items in the dbTable should be removed.
                    foreach (var dbItem in dbTable)
                    {
                        Delete(dbItem.Value, navigationEntry, visited);
                    }

                    // let EF do the rest of the work.
                    navigationEntry.CurrentValue = mergedList;
                }
                else
                {
                    if (!visited.Contains(navigationEntry.CurrentValue)) // avoid stack overflow! (this might be also done checking if the property is dependent to parent)
                    {
                        if (entityServices.Equal(detachedValue, navigationEntry.CurrentValue))
                        {
                            // merge owned references and do nothing for associated references.
                            if (owned)
                            {
                                navigationEntry.CurrentValue = Merge(detachedValue, navigationEntry.CurrentValue, navigationEntry, visited).Entity;
                            }
                        }
                        else
                        {
                            if (navigationEntry.CurrentValue != null)
                            {
                                if (owned)
                                {
                                    Delete(navigationEntry.CurrentValue, navigationEntry, visited);
                                }
                            }

                            if (detachedValue != null)
                            {
                                if (owned)
                                {
                                    navigationEntry.CurrentValue = Add(detachedValue, navigationEntry, visited).Entity;
                                }
                                else
                                {
                                    navigationEntry.CurrentValue = Attach(detachedValue, navigationEntry).Entity;
                                }
                            }
                            else
                            {
                                navigationEntry.CurrentValue = null;
                            }
                        }
                    }
                }
            }

            return(_eventManager.OnEntityMerged(detached, persistedEntry, modified, parentNavigation).EntityEntry);
        }