public static object NextSkippingSentinel([NotNull] this ValueGenerator valueGenerator, [NotNull] IProperty property) { var value = valueGenerator.Next(); if (property.IsSentinelValue(value)) { value = valueGenerator.Next(); } return(value); }
/// <summary> /// Updates the database-generated properties for <paramref name="internalEntityEntry"/>. /// </summary> /// <param name="internalEntityEntry">The <see cref="IUpdateEntry"/> the <see cref="IUpdateEntry"/> representing the document being updated.</param> protected void UpdateDbGeneratedProperties(InternalEntityEntry internalEntityEntry) { var entityEntry = internalEntityEntry.ToEntityEntry(); foreach (IProperty property in _dbGeneratedProperties) { ValueGenerator valueGenerator = _valueGeneratorSelector.Select(property, internalEntityEntry.EntityType); object dbGeneratedValue = valueGenerator.Next(entityEntry); internalEntityEntry.SetProperty(property, dbGeneratedValue, true); property.GetSetter().SetClrValue(internalEntityEntry.Entity, dbGeneratedValue); } }
public static Guid NewSquentialGuid() { return(_generator.Next(null)); }
public override Identifier Next(EntityEntry entry) { Identifier id = new Identifier(_valueGenerator.Next(entry)); return(id); }
/// <summary> /// Initializes a new instance of the <see cref="SaveChangesHelper" /> class. /// </summary> /// <param name="dbContext"> <see cref="DbContext" /> against which the requested query will be executed. </param> /// <param name="request"> The <see cref="SaveChangesRequest" /> object from the client containing the updated entities. </param> public SaveChangesHelper(DbContext dbContext, SaveChangesRequest request) { this.dbContext = dbContext; var typeMap = this.dbContext.Model.GetEntityTypes().ToDictionary(x => x.DisplayName()); var stateManager = this.dbContext.GetService <IStateManager>(); var entityMaterializerSource = this.dbContext.GetService <IEntityMaterializerSource>(); // Materialize entities and add entries to dbContext EntityEntry MaterializeAndTrackEntity(UpdateEntryDto dto) { IEntityType entityType = typeMap[dto.EntityTypeName]; object MaterializeEntity() { var valueBuffer = new ValueBuffer(dto.GetCurrentValues(entityType, request.Mapper)); var materializationContext = new MaterializationContext(valueBuffer, this.dbContext); return(entityMaterializerSource.GetMaterializer(entityType).Invoke(materializationContext)); } EntityEntry entry; if (entityType.HasDefiningNavigation()) { IKey key = entityType.DefiningEntityType.FindPrimaryKey(); object[] keyValues = dto.GetDelegatedIdentityKeys(request.Mapper, key); // Here we assume that the owner entry is already present in the context EntityEntry ownerEntry = stateManager.TryGetEntry(key, keyValues).ToEntityEntry(); ReferenceEntry referenceEntry = ownerEntry.Reference(entityType.DefiningNavigationName); if (referenceEntry.CurrentValue == null) { referenceEntry.CurrentValue = MaterializeEntity(); } entry = referenceEntry.TargetEntry; } else { entry = stateManager.GetOrCreateEntry(MaterializeEntity()).ToEntityEntry(); } // Correlate properties of DTO and entry var props = dto.JoinScalarProperties(entry, request.Mapper); // Set Key properties foreach (var p in props.Where(x => x.EfProperty.Metadata.IsKey())) { p.EfProperty.CurrentValue = p.CurrentValue; if (p.EfProperty.Metadata.GetOriginalValueIndex() >= 0) { p.EfProperty.OriginalValue = p.OriginalValue; } } // Set EntityState after PK values (temp or perm) are set. // This will add entities to identity map. entry.State = dto.EntityState; // Set non key properties foreach (var p in props.Where(x => !x.EfProperty.Metadata.IsKey())) { bool canSetCurrentValue = p.EfProperty.Metadata.IsShadowProperty || p.EfProperty.Metadata.TryGetMemberInfo(forConstruction: false, forSet: true, out _, out _); if (canSetCurrentValue) { p.EfProperty.CurrentValue = p.CurrentValue; } if (p.EfProperty.Metadata.GetOriginalValueIndex() >= 0 && p.EfProperty.OriginalValue != p.OriginalValue) { p.EfProperty.OriginalValue = p.OriginalValue; } if (canSetCurrentValue) { p.EfProperty.IsModified = p.DtoProperty.IsModified; } } // Mark temporary property values foreach (var p in props.Where(x => x.DtoProperty.IsTemporary)) { p.EfProperty.IsTemporary = true; } return(entry); } request.SharedIdentityDataTransferObjects.ForEach(dto => MaterializeAndTrackEntity(dto)); var entries = request.DataTransferObjects.Select(MaterializeAndTrackEntity).ToList(); // Replace temporary PKs coming from client with generated values (e.g. HiLoSequence) var valueGeneratorSelector = this.dbContext.GetService <IValueGeneratorSelector>(); foreach (EntityEntry entry in entries) { foreach (PropertyEntry tempPk in entry.Properties.Where(p => p.IsTemporary && p.Metadata.IsKey() && p.Metadata.RequiresValueGenerator()).ToList()) { ValueGenerator valueGenerator = valueGeneratorSelector.Select(tempPk.Metadata, entry.Metadata); if (!valueGenerator.GeneratesTemporaryValues) { tempPk.CurrentValue = valueGenerator.Next(entry); tempPk.IsTemporary = false; } } } this.Entries = entries.Select(e => e.GetInfrastructure()).ToList(); }