/// <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> /// 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([NotNull] IUpdateEntry entry, int?ordinal) { var document = new JObject(); foreach (var property in entry.EntityType.GetProperties()) { var storeName = property.GetJsonPropertyName(); if (storeName.Length != 0) { document[storeName] = ConvertPropertyValue(property, entry.GetCurrentValue(property)); } else if (entry.HasTemporaryValue(property)) { if (ordinal != null && property.IsOrdinalKeyProperty()) { entry.SetStoreGeneratedValue(property, ordinal.Value); } } } foreach (var embeddedNavigation in entry.EntityType.GetNavigations()) { var fk = embeddedNavigation.ForeignKey; if (!fk.IsOwnership || embeddedNavigation.IsOnDependent || fk.DeclaringEntityType.IsDocumentRoot()) { continue; } var embeddedValue = entry.GetCurrentValue(embeddedNavigation); var embeddedPropertyName = fk.DeclaringEntityType.GetContainingPropertyName(); 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 embeddedOrdinal = 0; 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, embeddedOrdinal)); embeddedOrdinal++; } document[embeddedPropertyName] = array; } } return(document); }
/// <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); }
/// <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 UpdateDocument([NotNull] JObject document, [NotNull] IUpdateEntry entry, int?ordinal) { var anyPropertyUpdated = false; #pragma warning disable EF1001 // Internal EF Core API usage. // #16707 var stateManager = ((InternalEntityEntry)entry).StateManager; #pragma warning restore EF1001 // Internal EF Core API usage. foreach (var property in entry.EntityType.GetProperties()) { if (entry.EntityState == EntityState.Added || entry.IsModified(property)) { var storeName = property.GetJsonPropertyName(); if (storeName.Length != 0) { document[storeName] = ConvertPropertyValue(property, entry.GetCurrentValue(property)); anyPropertyUpdated = true; } } if (ordinal != null && entry.HasTemporaryValue(property) && property.IsOrdinalKeyProperty()) { entry.SetStoreGeneratedValue(property, ordinal.Value); } } foreach (var ownedNavigation in entry.EntityType.GetNavigations()) { var fk = ownedNavigation.ForeignKey; if (!fk.IsOwnership || ownedNavigation.IsOnDependent || fk.DeclaringEntityType.IsDocumentRoot()) { continue; } var embeddedDocumentSource = _database.GetDocumentSource(fk.DeclaringEntityType); var embeddedValue = entry.GetCurrentValue(ownedNavigation); var embeddedPropertyName = fk.DeclaringEntityType.GetContainingPropertyName(); if (embeddedValue == null) { if (document[embeddedPropertyName] != null) { document[embeddedPropertyName] = null; anyPropertyUpdated = true; } } else if (fk.IsUnique) { #pragma warning disable EF1001 // Internal EF Core API usage. // #16707 var embeddedEntry = ((InternalEntityEntry)entry).StateManager.TryGetEntry(embeddedValue, fk.DeclaringEntityType); #pragma warning restore EF1001 // Internal EF Core API usage. if (embeddedEntry == null) { continue; } var embeddedDocument = embeddedDocumentSource.GetCurrentDocument(embeddedEntry); embeddedDocument = embeddedDocument != null ? embeddedDocumentSource.UpdateDocument(embeddedDocument, embeddedEntry) : embeddedDocumentSource.CreateDocument(embeddedEntry); if (embeddedDocument != null) { document[embeddedPropertyName] = embeddedDocument; anyPropertyUpdated = true; } } else { var embeddedOrdinal = 0; var ordinalKeyProperty = GetOrdinalKeyProperty(fk.DeclaringEntityType); if (ordinalKeyProperty != null) { var shouldSetTemporaryKeys = false; foreach (var dependent in (IEnumerable)embeddedValue) { #pragma warning disable EF1001 // Internal EF Core API usage. // #16707 var embeddedEntry = stateManager.TryGetEntry(dependent, fk.DeclaringEntityType); if (embeddedEntry == null) { continue; } if ((int)embeddedEntry.GetCurrentValue(ordinalKeyProperty) != embeddedOrdinal) { shouldSetTemporaryKeys = true; break; } #pragma warning restore EF1001 // Internal EF Core API usage. embeddedOrdinal++; } if (shouldSetTemporaryKeys) { var temporaryOrdinal = -1; foreach (var dependent in (IEnumerable)embeddedValue) { #pragma warning disable EF1001 // Internal EF Core API usage. // #16707 var embeddedEntry = stateManager.TryGetEntry(dependent, fk.DeclaringEntityType); if (embeddedEntry == null) { continue; } embeddedEntry.SetTemporaryValue(ordinalKeyProperty, temporaryOrdinal, setModified: false); #pragma warning restore EF1001 // Internal EF Core API usage. temporaryOrdinal--; } } } embeddedOrdinal = 0; var array = new JArray(); foreach (var dependent in (IEnumerable)embeddedValue) { #pragma warning disable EF1001 // Internal EF Core API usage. // #16707 var embeddedEntry = ((InternalEntityEntry)entry).StateManager.TryGetEntry(dependent, fk.DeclaringEntityType); #pragma warning restore EF1001 // Internal EF Core API usage. if (embeddedEntry == null) { continue; } var embeddedDocument = embeddedDocumentSource.GetCurrentDocument(embeddedEntry); embeddedDocument = embeddedDocument != null ? embeddedDocumentSource.UpdateDocument(embeddedDocument, embeddedEntry, embeddedOrdinal) ?? embeddedDocument : embeddedDocumentSource.CreateDocument(embeddedEntry, embeddedOrdinal); array.Add(embeddedDocument); embeddedOrdinal++; } document[embeddedPropertyName] = array; anyPropertyUpdated = true; } } return(anyPropertyUpdated ? document : 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 JObject UpdateDocument(JObject document, IUpdateEntry entry) { var anyPropertyUpdated = false; foreach (var property in entry.EntityType.GetProperties()) { if (entry.EntityState == EntityState.Added || entry.IsModified(property)) { var storeName = property.GetCosmosPropertyName(); if (storeName.Length != 0) { document[storeName] = ConvertPropertyValue(property, entry.GetCurrentValue(property)); anyPropertyUpdated = true; } else if (entry.HasTemporaryValue(property)) { ((InternalEntityEntry)entry)[property] = entry.GetCurrentValue(property); } } } foreach (var ownedNavigation in entry.EntityType.GetNavigations()) { var fk = ownedNavigation.ForeignKey; if (!fk.IsOwnership || ownedNavigation.IsDependentToPrincipal() || fk.DeclaringEntityType.IsDocumentRoot()) { continue; } var embeddedDocumentSource = _database.GetDocumentSource(fk.DeclaringEntityType); var embeddedValue = entry.GetCurrentValue(ownedNavigation); var embeddedPropertyName = fk.DeclaringEntityType.GetCosmosContainingPropertyName(); if (embeddedValue == null) { if (document[embeddedPropertyName] != null) { document[embeddedPropertyName] = null; anyPropertyUpdated = true; } } else if (fk.IsUnique) { var embeddedEntry = ((InternalEntityEntry)entry).StateManager.TryGetEntry(embeddedValue, fk.DeclaringEntityType); if (embeddedEntry == null) { continue; } var embeddedDocument = embeddedDocumentSource.GetCurrentDocument(embeddedEntry); embeddedDocument = embeddedDocument != null ? embeddedDocumentSource.UpdateDocument(embeddedDocument, embeddedEntry) : embeddedDocumentSource.CreateDocument(embeddedEntry); if (embeddedDocument != null) { document[embeddedPropertyName] = embeddedDocument; anyPropertyUpdated = true; } } else { var array = new JArray(); foreach (var dependent in (IEnumerable)embeddedValue) { var embeddedEntry = ((InternalEntityEntry)entry).StateManager.TryGetEntry(dependent, fk.DeclaringEntityType); if (embeddedEntry == null) { continue; } var embeddedDocument = embeddedDocumentSource.GetCurrentDocument(embeddedEntry); embeddedDocument = embeddedDocument != null ? embeddedDocumentSource.UpdateDocument(embeddedDocument, embeddedEntry) ?? embeddedDocument : embeddedDocumentSource.CreateDocument(embeddedEntry); array.Add(embeddedDocument); } document[embeddedPropertyName] = array; anyPropertyUpdated = true; } } return(anyPropertyUpdated ? document : null); }