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); }
private static T GetValueFromEntity <T>(IClrPropertyGetter clrPropertyGetter, object entity) { if (entity == null) { return(default(T)); } return((T)clrPropertyGetter.GetClrValue(entity)); }
/// <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 void Get(object instance, object[] result, ref int offset) { object entity = _entityGetter.GetClrValue(instance); if (entity == null) { throw new Exception(""); } foreach (IClrPropertyGetter getter in _keyGetters) { result[offset] = getter.GetClrValue(entity); offset++; } }
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; }
public void Get(object instance, object[] result, ref int offset) { result[offset] = _keyGetter.GetClrValue(instance); offset++; }
/// <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 override void AddDbParameter(DbCommand command, object?value) { Check.DebugAssert(value != null, "value is null"); base.AddDbParameter(command, _clrPropertyGetter.GetClrValue(value)); }
public override void AddDbParameter(DbCommand command, object value) { Debug.Assert(value != null); base.AddDbParameter(command, _clrPropertyGetter.GetClrValue(value)); }
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); }
/// <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); } } }
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); }