/// <inheritdoc /> /// <summary> /// Creates an <see cref="UpdateOneModel{TEntity}"/> that maps the given <paramref name="updateEntry"/>. /// </summary> /// <param name="updateEntry">The <see cref="IUpdateEntry"/> to map.</param> /// <returns>A new <see cref="UpdateOneModel{TEntity}"/> containing the inserted values represented /// by <paramref name="updateEntry"/>.</returns> public override WriteModel <TEntity> CreateWriteModel(IUpdateEntry updateEntry) { InternalEntityEntry internalEntityEntry = Check.Is <InternalEntityEntry>(updateEntry, nameof(updateEntry)); UpdateDbGeneratedProperties(internalEntityEntry); return(new ReplaceOneModel <TEntity>( GetLookupFilter(updateEntry), (TEntity)internalEntityEntry.Entity)); }
/// <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 virtual void Create(IUpdateEntry entry) { var row = entry.EntityType.GetProperties() .Select(p => SnapshotValue(p, GetStructuralComparer(p), entry)) .ToArray(); _rows.Add(CreateKey(entry), row); BumpValueGenerators(row); }
private Task <bool> SaveAsync(IUpdateEntry entry, CancellationToken cancellationToken) { var entityType = entry.EntityType; var documentSource = GetDocumentSource(entityType); var collectionId = documentSource.GetCollectionId(); var state = entry.EntityState; if (entry.SharedIdentityEntry != null) { if (entry.EntityState == EntityState.Deleted) { return(Task.FromResult(false)); } if (state == EntityState.Added) { state = EntityState.Modified; } } switch (state) { case EntityState.Added: var newDocument = documentSource.CreateDocument(entry); return(_cosmosClient.CreateItemAsync(collectionId, newDocument, GetPartitionKey(entry), cancellationToken)); case EntityState.Modified: var document = documentSource.GetCurrentDocument(entry); if (document != null) { if (documentSource.UpdateDocument(document, entry) == null) { return(Task.FromResult(false)); } } else { document = documentSource.CreateDocument(entry); document[entityType.GetDiscriminatorProperty().GetCosmosPropertyName()] = JToken.FromObject(entityType.GetDiscriminatorValue(), CosmosClientWrapper.Serializer); } return(_cosmosClient.ReplaceItemAsync( collectionId, documentSource.GetId(entry.SharedIdentityEntry ?? entry), document, GetPartitionKey(entry), cancellationToken)); case EntityState.Deleted: return(_cosmosClient.DeleteItemAsync( collectionId, documentSource.GetId(entry), GetPartitionKey(entry), cancellationToken)); default: return(Task.FromResult(false)); } }
private Task <bool> SaveAsync(IUpdateEntry entry, CancellationToken cancellationToken) { var entityType = entry.EntityType; var documentSource = GetDocumentSource(entityType); var collectionId = documentSource.GetCollectionId(); var state = entry.EntityState; if (entry.SharedIdentityEntry != null) { if (entry.EntityState == EntityState.Deleted) { return(Task.FromResult(false)); } if (state == EntityState.Added) { state = EntityState.Modified; } } switch (state) { case EntityState.Added: return(_cosmosClient.CreateDocumentAsync(collectionId, documentSource.CreateDocument(entry), cancellationToken)); case EntityState.Modified: var jObjectProperty = entityType.FindProperty(StoreKeyConvention.JObjectPropertyName); var document = jObjectProperty != null ? (JObject)(entry.SharedIdentityEntry ?? entry).GetCurrentValue(jObjectProperty) : null; if (document != null) { if (documentSource.UpdateDocument(document, entry) == null) { return(Task.FromResult(false)); } } else { document = documentSource.CreateDocument(entry); document[entityType.Cosmos().DiscriminatorProperty.Cosmos().PropertyName] = JToken.FromObject(entityType.Cosmos().DiscriminatorValue); } return(_cosmosClient.ReplaceDocumentAsync( collectionId, documentSource.GetId(entry.SharedIdentityEntry ?? entry), document, cancellationToken)); case EntityState.Deleted: return(_cosmosClient.DeleteDocumentAsync(collectionId, documentSource.GetId(entry), cancellationToken)); default: return(Task.FromResult(false)); } }
/// <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 virtual void Remove(IUpdateEntry entry) { if (_foreignKey.DeclaringEntityType.IsAssignableFrom(entry.EntityType) && TryCreateFromCurrentValues(entry, out var key)) { if (_map.TryGetValue(key, out var dependents)) { dependents.Remove(entry); } } }
/// <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 int Compare(IUpdateEntry x, IUpdateEntry y) { var xValue = GetCurrentValue(x); var yValue = GetCurrentValue(y); return(xValue is Array xArray && yValue is Array yArray && xArray.Length != yArray.Length ? xArray.Length - yArray.Length : base.Compare(xValue, yValue)); }
private JObject CreateDocument(IUpdateEntry entry) { var document = new JObject(); foreach (var property in _entityType.GetProperties()) { var value = entry.GetCurrentValue(property); document[property.Name] = value != null?JToken.FromObject(value) : null; } return(document); }
#pragma warning restore EF1001 // Internal EF Core API usage. private Exception ThrowUpdateException(CosmosException exception, IUpdateEntry entry) { var documentSource = GetDocumentSource(entry.EntityType); var id = documentSource.GetId(entry.SharedIdentityEntry ?? entry); throw exception.StatusCode switch { HttpStatusCode.PreconditionFailed => new DbUpdateConcurrencyException(CosmosStrings.UpdateConflict(id), exception, new[] { entry }), HttpStatusCode.Conflict => new DbUpdateException(CosmosStrings.UpdateConflict(id), exception, new[] { entry }), _ => Rethrow(exception), }; }
/// <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 virtual JObject CreateDocument(IUpdateEntry entry) { var document = new JObject(); foreach (var property in entry.EntityType.GetProperties()) { var storeName = property.GetCosmosPropertyName(); if (storeName.Length != 0) { document[storeName] = ConvertPropertyValue(property, entry.GetCurrentValue(property)); } else if (entry.HasTemporaryValue(property)) { ((InternalEntityEntry)entry)[property] = entry.GetCurrentValue(property); } } foreach (var embeddedNavigation in entry.EntityType.GetNavigations()) { var fk = embeddedNavigation.ForeignKey; if (!fk.IsOwnership || embeddedNavigation.IsDependentToPrincipal() || fk.DeclaringEntityType.IsDocumentRoot()) { continue; } var embeddedValue = entry.GetCurrentValue(embeddedNavigation); var embeddedPropertyName = fk.DeclaringEntityType.GetCosmosContainingPropertyName(); if (embeddedValue == null) { document[embeddedPropertyName] = null; } else if (fk.IsUnique) { var dependentEntry = ((InternalEntityEntry)entry).StateManager.TryGetEntry(embeddedValue, fk.DeclaringEntityType); document[embeddedPropertyName] = _database.GetDocumentSource(dependentEntry.EntityType).CreateDocument(dependentEntry); } else { var array = new JArray(); foreach (var dependent in (IEnumerable)embeddedValue) { var dependentEntry = ((InternalEntityEntry)entry).StateManager.TryGetEntry(dependent, fk.DeclaringEntityType); array.Add(_database.GetDocumentSource(dependentEntry.EntityType).CreateDocument(dependentEntry)); } document[embeddedPropertyName] = array; } } return(document); }
private UpdateDefinition <TEntity> CreatePropertyUpdateDefinition( UpdateDefinitionBuilder <TEntity> builder, IUpdateEntry entityEntry, IPropertyBase property) => (UpdateDefinition <TEntity>)SetMethodInfo .MakeGenericMethod(property.ClrType) .Invoke( builder, new [] { CreateFieldDefintion(property), entityEntry.GetCurrentValue(property) });
/// <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) { TKey key = CreateKey(entry); if (_rows.ContainsKey(key)) { _rows.Remove(key); } else { throw new DbUpdateConcurrencyException(FileContextStrings.UpdateConcurrencyException, new[] { entry }); } }
private static FilterDefinition <TEntity> GetIdFilter <TEntity>(IUpdateEntry updateEntry) { IList <FilterDefinition <TEntity> > filterDefinitions = updateEntry.EntityType .FindPrimaryKey() .Properties .Select(property => GetPropertyFilterDefinition <TEntity>(property, updateEntry.GetCurrentValue(property))) .DefaultIfEmpty(Builders <TEntity> .Filter.Empty) .ToList(); return(filterDefinitions.Count > 1 ? Builders <TEntity> .Filter.And(filterDefinitions) : filterDefinitions[index : 0]); }
private object[] CreateFromEntry( IUpdateEntry entry, Func <IUpdateEntry, IProperty, object?> getValue) { var values = new object[Properties.Count]; var index = 0; foreach (var property in Properties) { var value = getValue(entry, property); if (value == null) { return(default !);
/// <summary> /// Adds an <see cref="IUpdateEntry" /> to this command representing an entity to be inserted, updated, or deleted. /// </summary> /// <param name="entry"> The entry representing the entity to add. </param> /// <param name="mainEntry"> A value indicating whether this is the main entry for the row. </param> public virtual void AddEntry([NotNull] IUpdateEntry entry, bool mainEntry) { Check.NotNull(entry, nameof(entry)); switch (entry.EntityState) { case EntityState.Deleted: case EntityState.Modified: case EntityState.Added: break; default: if (_sensitiveLoggingEnabled) { throw new InvalidOperationException( RelationalStrings.ModificationCommandInvalidEntityStateSensitive( entry.EntityType.DisplayName(), entry.BuildCurrentValuesString(entry.EntityType.FindPrimaryKey().Properties), entry.EntityState)); } throw new InvalidOperationException( RelationalStrings.ModificationCommandInvalidEntityState( entry.EntityType.DisplayName(), entry.EntityState)); } if (mainEntry) { Check.DebugAssert(!_mainEntryAdded, "Only expected a single main entry"); for (var i = 0; i < _entries.Count; i++) { ValidateState(entry, _entries[i]); } _mainEntryAdded = true; _entries.Insert(0, entry); } else { if (_mainEntryAdded) { ValidateState(_entries[0], entry); } _entries.Add(entry); } _columnModifications = null; }
/// <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 virtual TValue GetOrAddValue([NotNull] IUpdateEntry entry, [NotNull] SharedTableEntryValueFactory <TValue> createElement) { var mainEntry = GetMainEntry(entry); if (_entryValueMap.TryGetValue(mainEntry, out var sharedCommand)) { return(sharedCommand); } sharedCommand = createElement(_table.Name, _table.Schema, _comparer); _entryValueMap.Add(mainEntry, sharedCommand); return(sharedCommand); }
/// <summary> /// Adds an <see cref="IUpdateEntry" /> to this command representing an entity to be inserted, updated, or deleted. /// </summary> /// <param name="entry"> The entry representing the entity to add. </param> public virtual void AddEntry([NotNull] IUpdateEntry entry) { Check.NotNull(entry, nameof(entry)); switch (entry.EntityState) { case EntityState.Deleted: case EntityState.Modified: case EntityState.Added: break; default: throw new ArgumentException(RelationalStrings.ModificationCommandInvalidEntityState(entry.EntityState)); } if (_entries.Count > 0) { var lastEntry = _entries[_entries.Count - 1]; var lastEntryState = lastEntry.SharedIdentityEntry == null ? lastEntry.EntityState : EntityState.Modified; var entryState = entry.SharedIdentityEntry == null ? entry.EntityState : EntityState.Modified; if (lastEntryState != entryState) { if (_sensitiveLoggingEnabled) { throw new InvalidOperationException( RelationalStrings.ConflictingRowUpdateTypesSensitive( entry.EntityType.DisplayName(), entry.BuildCurrentValuesString(entry.EntityType.FindPrimaryKey().Properties), entryState, lastEntry.EntityType.DisplayName(), lastEntry.BuildCurrentValuesString(lastEntry.EntityType.FindPrimaryKey().Properties), lastEntryState)); } throw new InvalidOperationException( RelationalStrings.ConflictingRowUpdateTypes( entry.EntityType.DisplayName(), entryState, lastEntry.EntityType.DisplayName(), lastEntryState)); } } _entries.Add(entry); _columnModifications = null; }
/// <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 virtual int Compare(IUpdateEntry x, IUpdateEntry y) { var xValue = x.GetCurrentValue <TModel>(_property); var yValue = y.GetCurrentValue <TModel>(_property); return(xValue == null && yValue == null ? 0 : xValue == null ? -1 : yValue == null ? 1 : _underlyingComparer.Compare(_converter(xValue), _converter(yValue))); }
/// <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 virtual int Compare(IUpdateEntry x, IUpdateEntry y) { var xValue = x.GetCurrentValue <TModel?>(_property); var yValue = y.GetCurrentValue <TModel?>(_property); return(!xValue.HasValue && !yValue.HasValue ? 0 : !xValue.HasValue ? -1 : !yValue.HasValue ? 1 : _underlyingComparer.Compare(_converter(xValue.Value), _converter(yValue.Value))); }
public bool TryPropagate(IProperty property, IUpdateEntry entry) { if (_write && (entry.EntityState == EntityState.Unchanged || (entry.EntityState == EntityState.Modified && !entry.IsModified(property)) || (entry.EntityState == EntityState.Added && Equals(_originalValue, entry.GetCurrentValue(property))))) { ((InternalEntityEntry)entry)[property] = _currentValue; return(false); } return(_write); }
private JObject UpdateDocument(JObject document, IUpdateEntry entry) { foreach (var property in _entityType.GetProperties()) { if (property.Name != StoreKeyConvention.JObjectPropertyName && entry.IsModified(property)) { var value = entry.GetCurrentValue(property); document[property.Name] = value != null?JToken.FromObject(value) : null; } } return(document); }
/// <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 TValue GetOrAddValue([NotNull] IUpdateEntry entry) { var mainEntry = GetMainEntry((InternalEntityEntry)entry); if (_entryValueMap.TryGetValue(mainEntry, out var sharedCommand)) { return(sharedCommand); } sharedCommand = _createElement(_name, _schema, _comparer); _entryValueMap.Add(mainEntry, sharedCommand); return(sharedCommand); }
private bool TryCreateFromCurrentValues(IUpdateEntry entry, [NotNullWhen(true)] out TKey?key) { // TODO: Move into delegate foreach (var property in _foreignKey.Properties) { if (entry.IsConceptualNull(property)) { key = default; return(false); } } return(_dependentKeyValueFactory.TryCreateFromCurrentValues(entry, out key)); }
/// <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 virtual void Add(IUpdateEntry entry) { if (_foreignKey.DeclaringEntityType.IsAssignableFrom(entry.EntityType) && TryCreateFromCurrentValues(entry, out var key)) { if (!_map.TryGetValue(key, out var dependents)) { dependents = new HashSet <IUpdateEntry>(); _map[key] = dependents; } dependents.Add(entry); } }
public bool TryPropagate(IProperty property, IUpdateEntry entry) { if (_write && (entry.EntityState == EntityState.Unchanged || (entry.EntityState == EntityState.Modified && !entry.IsModified(property)) || (entry.EntityState == EntityState.Added && Equals(_originalValue, entry.GetCurrentValue(property))))) { entry.SetStoreGeneratedValue(property, _currentValue); return(false); } return(_write); }
private Document CreateDocument(string id, IUpdateEntry entry) { var document = new Document { Id = id }; foreach (var property in _entityType.GetProperties()) { document.SetPropertyValue(property.Name, entry.GetCurrentValue(property)); } return(document); }
/// <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); var value = _docrows.FindById(new BsonValue(key)); if (value != null) { _docrows.Delete(new BsonValue(key)); } else { throw new DbUpdateConcurrencyException(LiteDBStrings.UpdateConcurrencyException, new[] { entry }); } }
private bool Save(IUpdateEntry entry) { var entityType = entry.EntityType; var documentSource = GetDocumentSource(entityType); var collectionId = documentSource.GetCollectionId(); var state = entry.EntityState; if (entry.SharedIdentityEntry != null) { if (entry.EntityState == EntityState.Deleted) { return(false); } if (state == EntityState.Added) { state = EntityState.Modified; } } switch (state) { case EntityState.Added: return(_cosmosClient.CreateDocument(collectionId, documentSource.CreateDocument(entry))); case EntityState.Modified: var jObjectProperty = entityType.FindProperty(StoreKeyConvention.JObjectPropertyName); var document = jObjectProperty != null ? (JObject)(entry.SharedIdentityEntry ?? entry).GetCurrentValue(jObjectProperty) : null; if (document != null) { documentSource.UpdateDocument(document, entry); } else { document = documentSource.CreateDocument(entry); } return(_cosmosClient.ReplaceDocument( collectionId, documentSource.GetId(entry.SharedIdentityEntry ?? entry), document)); case EntityState.Deleted: return(_cosmosClient.DeleteDocument(collectionId, documentSource.GetId(entry))); default: return(false); } }
public JObject CreateDocument(IUpdateEntry entry) { var document = new JObject(); foreach (var property in entry.EntityType.GetProperties()) { var storeName = property.Cosmos().PropertyName; if (storeName != "") { var value = entry.GetCurrentValue(property); document[storeName] = value != null?JToken.FromObject(value) : null; } } foreach (var ownedNavigation in entry.EntityType.GetNavigations()) { var fk = ownedNavigation.ForeignKey; if (!fk.IsOwnership || ownedNavigation.IsDependentToPrincipal() || fk.DeclaringEntityType.IsDocumentRoot()) { continue; } var nestedValue = entry.GetCurrentValue(ownedNavigation); if (nestedValue == null) { document[ownedNavigation.Name] = null; } else if (fk.IsUnique) { var dependentEntry = ((InternalEntityEntry)entry).StateManager.TryGetEntry(nestedValue, fk.DeclaringEntityType); document[ownedNavigation.Name] = _database.GetDocumentSource(dependentEntry.EntityType).CreateDocument(dependentEntry); } else { var array = new JArray(); foreach (var dependent in (IEnumerable)nestedValue) { var dependentEntry = ((InternalEntityEntry)entry).StateManager.TryGetEntry(dependent, fk.DeclaringEntityType); array.Add(_database.GetDocumentSource(dependentEntry.EntityType).CreateDocument(dependentEntry)); } document[ownedNavigation.Name] = array; } } return(document); }
private StoreRecord <object> ConvertToObjectRecord(IUpdateEntry entry) { var entityType = entry.EntityType; var name = entityType.DisplayName(); var row = entityType.GetProperties() .Select(x => SnapshotValue(x, x.GetKeyValueComparer(), entry)) .ToArray(); return(new StoreRecord <object>() { Storename = name, Data = row, }); }
/// <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 ModificationCommand GetOrAddCommand([NotNull] IUpdateEntry entry) { var mainEntry = GetMainEntry((InternalEntityEntry)entry); if (_sharedCommands.TryGetValue(mainEntry, out var sharedCommand)) { return(sharedCommand); } sharedCommand = new ModificationCommand( _name, _schema, _generateParameterName, _sensitiveLoggingEnabled, _comparer); _sharedCommands.Add(mainEntry, sharedCommand); return(sharedCommand); }