public void RecordValue(IProperty property, IUpdateEntry entry) { switch (entry.EntityState) { case EntityState.Modified: if (!_write && entry.IsModified(property)) { _write = true; _currentValue = entry.GetCurrentValue(property); } break; case EntityState.Added: _currentValue = entry.GetCurrentValue(property); _write = !property.GetValueComparer().Equals(_originalValue, _currentValue); break; case EntityState.Deleted: _originalValue = entry.GetOriginalValue(property); if (!_write && !property.IsPrimaryKey()) { _write = true; _currentValue = null; } break; } }
/// <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 virtual void Delete(IUpdateEntry entry) { var key = CreateKey(entry); if (_rows.ContainsKey(key)) { var properties = entry.EntityType.GetProperties().ToList(); var concurrencyConflicts = new Dictionary <IProperty, object>(); for (var index = 0; index < properties.Count; index++) { if (properties[index].IsConcurrencyToken && !Equals(_rows[key][index], entry.GetOriginalValue(properties[index]))) { concurrencyConflicts.Add(properties[index], _rows[key][index]); } } if (concurrencyConflicts.Any()) { ThrowUpdateConcurrencyException(entry, concurrencyConflicts); } _rows.Remove(key); } else { throw new DbUpdateConcurrencyException(InMemoryStrings.UpdateConcurrencyException, new[] { entry }); } }
/// <summary> /// Initializes a new instance of the <see cref="UpdateEntryDto"/> class. /// </summary> /// <param name="entry">The state entry of an entity.</param> /// <param name="mapper">The <see cref="IDynamicObjectMapper" /> used for mapping the property values.</param> public UpdateEntryDto(IUpdateEntry entry, IDynamicObjectMapper mapper) { DynamicObject CreateValueDto(IProperty propertyBase, object value) { value = Utils.ConvertToProvider(value, propertyBase); return(mapper.MapObject(value)); } this.EntityTypeName = entry.EntityType.DisplayName(); this.EntityState = entry.EntityState; this.PropertyDatas = entry.ToEntityEntry().Properties.Select( prop => new PropertyData { Name = prop.Metadata.Name, OriginalValueDto = prop.Metadata.GetOriginalValueIndex() >= 0 ? CreateValueDto(prop.Metadata, prop.OriginalValue) : null, CurrentValueDto = CreateValueDto(prop.Metadata, prop.CurrentValue), IsModified = prop.IsModified, IsTemporary = prop.IsTemporary, }).ToList(); if (entry.EntityType.HasDefiningNavigation()) { var ownership = entry.EntityType.GetForeignKeys().Single(fk => fk.IsOwnership); this.DelegatedIdentityDatas = ownership.Properties.Select( prop => new PropertyData { Name = prop.Name, OriginalValueDto = CreateValueDto(prop, entry.GetOriginalValue(prop)), CurrentValueDto = CreateValueDto(prop, entry.GetCurrentValue(prop)), IsModified = entry.IsModified(prop), IsTemporary = entry.HasTemporaryValue(prop), }).ToList(); } }
/// <summary> /// Creates a formatted string representation of the given properties and their original /// values such as is useful when throwing exceptions about keys, indexes, etc. that use /// the properties. /// </summary> /// <param name="entry"> The entry from which values will be obtained. </param> /// <param name="properties"> The properties to format. </param> /// <returns> The string representation. </returns> public static string BuildOriginalValuesString( [NotNull] this IUpdateEntry entry, [NotNull] IEnumerable <IPropertyBase> properties) => "{" + string.Join( ", ", properties.Select(p => p.Name + ": " + Convert.ToString(entry.GetOriginalValue(p), CultureInfo.InvariantCulture))) + "}";
/// <summary> /// Creates a formatted string representation of the given properties and their original /// values such as is useful when throwing exceptions about keys, indexes, etc. that use /// the properties. /// </summary> /// <param name="entry"> The entry from which values will be obtained. </param> /// <param name="properties"> The properties to format. </param> /// <returns> The string representation. </returns> public static string BuildOriginalValuesString( this IUpdateEntry entry, IEnumerable <IPropertyBase> properties) => "{" + string.Join( ", ", properties.Select( p => { var originalValue = entry.GetOriginalValue(p); return(p.Name + ": " + (originalValue == null ? "<null>" : Convert.ToString(originalValue, CultureInfo.InvariantCulture))); })) + "}";
private static bool IsConcurrencyConflict( IUpdateEntry entry, IProperty property, object rowValue, Dictionary <IProperty, object> concurrencyConflicts) { if (property.IsConcurrencyToken && !StructuralComparisons.StructuralEqualityComparer.Equals( rowValue, entry.GetOriginalValue(property))) { concurrencyConflicts.Add(property, rowValue); return(true); } return(false); }
/// <summary> /// Generates a <see cref="FilterDefinition{TEntity}"/> for <paramref name="updateEntry"/>. /// </summary> /// <param name="updateEntry">The <see cref="IUpdateEntry"/> for the document being updated.</param> /// <returns>A new <see cref="FilterDefinition{TEntity}"/> that can matches the document in <paramref name="updateEntry"/>.</returns> protected FilterDefinition <TEntity> GetLookupFilter([NotNull] IUpdateEntry updateEntry) { IEnumerable <IProperty> lookupProperties = Check.NotNull(updateEntry, nameof(updateEntry)).EntityState == EntityState.Added ? _keyProperties : _keyProperties.Concat(_concurrencyProperties); IList <FilterDefinition <TEntity> > filterDefinitions = lookupProperties .Select(property => GetPropertyFilterDefinition( property, property.IsConcurrencyToken ? updateEntry.GetOriginalValue(property) : updateEntry.GetCurrentValue(property))) .DefaultIfEmpty(Builders <TEntity> .Filter.Empty) .ToList(); return(filterDefinitions.Count > 1 ? Builders <TEntity> .Filter.And(filterDefinitions) : filterDefinitions[0]); }
public void RecordValue(IProperty property, IUpdateEntry entry) { switch (entry.EntityState) { case EntityState.Modified: if (!_write && entry.IsModified(property)) { _write = true; _currentValue = entry.GetCurrentValue(property); } break; case EntityState.Added: _currentValue = entry.GetCurrentValue(property); var comparer = property.GetValueComparer() ?? property.FindTypeMapping()?.Comparer; if (comparer == null) { _write = !Equals(_originalValue, _currentValue); } else { _write = !comparer.Equals(_originalValue, _currentValue); } break; case EntityState.Deleted: _originalValue = entry.GetOriginalValue(property); if (!_write && !property.IsPrimaryKey()) { _write = true; _currentValue = null; } break; } }
/// <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 virtual void Update(IUpdateEntry entry) { var key = CreateKey(entry); if (_rows.ContainsKey(key)) { var properties = entry.EntityType.GetProperties().ToList(); var valueBuffer = new object[properties.Count]; var concurrencyConflicts = new Dictionary <IProperty, object>(); for (var index = 0; index < valueBuffer.Length; index++) { if (properties[index].IsConcurrencyToken && !Equals(_rows[key][index], entry.GetOriginalValue(properties[index]))) { concurrencyConflicts.Add(properties[index], _rows[key][index]); continue; } valueBuffer[index] = entry.IsModified(properties[index]) ? entry.GetCurrentValue(properties[index]) : _rows[key][index]; } if (concurrencyConflicts.Any()) { ThrowUpdateConcurrencyException(entry, concurrencyConflicts); } _rows[key] = valueBuffer; } else { throw new DbUpdateConcurrencyException(InMemoryStrings.UpdateConcurrencyException, new[] { entry }); } }
/// <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 static string BuildOriginalValuesString([NotNull] this IUpdateEntry entry, [NotNull] IEnumerable <IPropertyBase> properties) => string.Join(", ", properties.Select(p => p.Name + ":" + entry.GetOriginalValue(p)));