/// <summary> /// Creates the put entity command. /// </summary> /// <param name="entity">The entity.</param> /// <param name="documentMetadata">The document metadata.</param> /// <returns></returns> protected ICommandData CreatePutEntityCommand(object entity, DocumentMetadata documentMetadata) { string id; if (GenerateEntityIdOnTheClient.TryGetIdFromInstance(entity, out id) && documentMetadata.Key != null && documentMetadata.Key.Equals(id, StringComparison.InvariantCultureIgnoreCase) == false) { throw new InvalidOperationException("Entity " + entity.GetType().FullName + " had document key '" + documentMetadata.Key + "' but now has document key property '" + id + "'." + Environment.NewLine + "You cannot change the document key property of a entity loaded into the session"); } var json = EntityToJson.ConvertEntityToJson(documentMetadata.Key, entity, documentMetadata.Metadata); var etag = UseOptimisticConcurrency || documentMetadata.ForceConcurrencyCheck ? (documentMetadata.ETag ?? Guid.Empty) : (Guid?)null; return(new PutCommandData { Document = json, Etag = etag, Key = documentMetadata.Key, Metadata = (RavenJObject)documentMetadata.Metadata.CloneToken(), }); }
protected internal Task <string> GenerateDocumentKeyForStorageAsync(object entity) { if (entity is IDynamicMetaObjectProvider) { string id; if (GenerateEntityIdOnTheClient.TryGetIdFromDynamic(entity, out id)) { return(CompletedTask.With(id)); } else { return(GenerateKeyAsync(entity) .ContinueWith(task => { // If we generated a new id, store it back into the Id field so the client has access to to it if (task.Result != null) { GenerateEntityIdOnTheClient.TrySetIdOnDynamic(entity, task.Result); } return task.Result; })); } } return(GetOrGenerateDocumentKeyAsync(entity) .ContinueWith(task => { GenerateEntityIdOnTheClient.TrySetIdentity(entity, task.Result); return task.Result; })); }
internal Subscription(long id, string database, SubscriptionConnectionOptions options, IAsyncDatabaseCommands commands, IDatabaseChanges changes, DocumentConvention conventions, bool open, Func <Task> ensureOpenSubscription) { this.id = id; this.options = options; this.commands = commands; this.changes = changes; this.conventions = conventions; this.ensureOpenSubscription = ensureOpenSubscription; SubscriptionLifetimeTask = taskCompletionSource.Task; if (typeof(T) != typeof(RavenJObject)) { isStronglyTyped = true; generateEntityIdOnTheClient = new GenerateEntityIdOnTheClient(conventions, entity => AsyncHelpers.RunSync(() => conventions.GenerateDocumentKeyAsync(database, commands, entity))); } if (open) { Start(); } else { if (options.Strategy != SubscriptionOpeningStrategy.WaitForFree) { throw new InvalidOperationException("Subscription isn't open while its opening strategy is: " + options.Strategy); } } if (options.Strategy == SubscriptionOpeningStrategy.WaitForFree) { WaitForSubscriptionReleased(); } }
public Task StoreAsync(object entity) { string id; var hasId = GenerateEntityIdOnTheClient.TryGetIdFromInstance(entity, out id); return(StoreAsyncInternal(entity, null, null, forceConcurrencyCheck: hasId == false)); }
/// <summary> /// Stores the specified entity in the session. The entity will be saved when SaveChanges is called. /// </summary> public void Store(object entity) { string id; var hasId = GenerateEntityIdOnTheClient.TryGetIdFromInstance(entity, out id); StoreInternal(entity, null, null, forceConcurrencyCheck: hasId == false); }
private DocumentMetadata GetDocumentMetadata <T>(T instance) { DocumentMetadata value; if (entitiesAndMetadata.TryGetValue(instance, out value) == false) { string id; if (GenerateEntityIdOnTheClient.TryGetIdFromInstance(instance, out id) || (instance is IDynamicMetaObjectProvider && GenerateEntityIdOnTheClient.TryGetIdFromDynamic(instance, out id)) ) { AssertNoNonUniqueInstance(instance, id); var jsonDocument = GetJsonDocument(id); entitiesByKey[id] = instance; entitiesAndMetadata[instance] = value = new DocumentMetadata { ETag = UseOptimisticConcurrency ? (Guid?)Guid.Empty : null, Key = id, OriginalMetadata = jsonDocument.Metadata, Metadata = (RavenJObject)jsonDocument.Metadata.CloneToken(), OriginalValue = new RavenJObject() }; } else { throw new InvalidOperationException("Could not find the document key for " + instance); } } return(value); }
/// <summary> /// Determines if the entity have changed. /// </summary> /// <param name="entity">The entity.</param> /// <param name="documentMetadata">The document metadata.</param> /// <returns></returns> protected bool EntityChanged(object entity, DocumentMetadata documentMetadata) { if (documentMetadata == null) { return(true); } string id; if (GenerateEntityIdOnTheClient.TryGetIdFromInstance(entity, out id) && string.Equals(documentMetadata.Key, id, StringComparison.InvariantCultureIgnoreCase) == false) { return(true); } // prevent saves of a modified read only entity if (documentMetadata.OriginalMetadata.ContainsKey(Constants.RavenReadOnly) && documentMetadata.OriginalMetadata.Value <bool>(Constants.RavenReadOnly) && documentMetadata.Metadata.ContainsKey(Constants.RavenReadOnly) && documentMetadata.Metadata.Value <bool>(Constants.RavenReadOnly)) { return(false); } var newObj = EntityToJson.ConvertEntityToJson(documentMetadata.Key, entity, documentMetadata.Metadata); return(RavenJToken.DeepEquals(newObj, documentMetadata.OriginalValue) == false || RavenJToken.DeepEquals(documentMetadata.Metadata, documentMetadata.OriginalMetadata) == false); }
public BulkInsertOperation(string database, IDocumentStore documentStore, DocumentSessionListeners listeners, BulkInsertOptions options) { this.documentStore = documentStore; databaseCommands = database == null ? documentStore.DatabaseCommands.ForSystemDatabase() : documentStore.DatabaseCommands.ForDatabase(database); generateEntityIdOnTheClient = new GenerateEntityIdOnTheClient(documentStore, entity => documentStore.Conventions.GenerateDocumentKey(database, databaseCommands, entity)); operation = databaseCommands.GetBulkInsertOperation(options); entityToJson = new EntityToJson(documentStore, listeners); }
public BulkInsertOperation(string database, IDocumentStore documentStore, DocumentSessionListeners listeners, BulkInsertOptions options) { this.documentStore = documentStore; databaseCommands = database == null ? documentStore.DatabaseCommands.ForSystemDatabase() : documentStore.DatabaseCommands.ForDatabase(database); generateEntityIdOnTheClient = new GenerateEntityIdOnTheClient(documentStore, entity => documentStore.Conventions.GenerateDocumentKey(database, databaseCommands, entity)); operation = databaseCommands.GetBulkInsertOperation(options); entityToJson = new EntityToJson(documentStore, listeners); }
public ShardedBulkInsertOperation(string database, ShardedDocumentStore shardedDocumentStore) { this.database = database; this.shardedDocumentStore = shardedDocumentStore; shards = shardedDocumentStore.ShardStrategy.Shards; Bulks = new Dictionary <string, BulkInsertOperation>(); generateEntityIdOnTheClient = new GenerateEntityIdOnTheClient(shardedDocumentStore.Conventions, entity => AsyncHelpers.RunSync(() => shardedDocumentStore.Conventions.GenerateDocumentKeyAsync(database, DatabaseCommands, entity))); shardResolutionStrategy = shardedDocumentStore.ShardStrategy.ShardResolutionStrategy; shardStrategy = this.shardedDocumentStore.ShardStrategy; }
public ShardedBulkInsertOperation(string database, ShardedDocumentStore shardedDocumentStore, BulkInsertOptions options) { this.database = database; this.shardedDocumentStore = shardedDocumentStore; this.options = options; shards = shardedDocumentStore.ShardStrategy.Shards; Bulks = new Dictionary<string, BulkInsertOperation>(); generateEntityIdOnTheClient = new GenerateEntityIdOnTheClient(shardedDocumentStore.Conventions, entity => AsyncHelpers.RunSync(() => shardedDocumentStore.Conventions.GenerateDocumentKeyAsync(database, DatabaseCommands, entity))); shardResolutionStrategy = shardedDocumentStore.ShardStrategy.ShardResolutionStrategy; shardStrategy = this.shardedDocumentStore.ShardStrategy; }
private void StoreInternal(object entity, Guid?etag, string id, bool forceConcurrencyCheck) { if (null == entity) { throw new ArgumentNullException("entity"); } DocumentMetadata value; if (entitiesAndMetadata.TryGetValue(entity, out value)) { value.ETag = etag ?? value.ETag; value.ForceConcurrencyCheck = forceConcurrencyCheck; return; } if (id == null) { if (GenerateDocumentKeysOnStore) { id = GenerateEntityIdOnTheClient.GenerateDocumentKeyForStorage(entity); } else { RememberEntityForDocumentKeyGeneration(entity); } } else { // Store it back into the Id field so the client has access to to it GenerateEntityIdOnTheClient.TrySetIdentity(entity, id); } // we make the check here even if we just generated the key // users can override the key generation behavior, and we need // to detect if they generate duplicates. AssertNoNonUniqueInstance(entity, id); var metadata = new RavenJObject(); var tag = documentStore.Conventions.GetTypeTagName(entity.GetType()); if (tag != null) { metadata.Add(Constants.RavenEntityName, tag); } if (id != null) { knownMissingIds.Remove(id); } StoreEntityInUnitOfWork(id, entity, etag, metadata, forceConcurrencyCheck); }
public BulkInsertOperation(string database, IDocumentStore documentStore, DocumentSessionListeners listeners, BulkInsertOptions options, IDatabaseChanges changes) { this.documentStore = documentStore; database = database ?? MultiDatabase.GetDatabaseName(documentStore.Url); // Fitzchak: Should not be ever null because of the above code, please refactor this. DatabaseCommands = database == null ? documentStore.AsyncDatabaseCommands.ForSystemDatabase() : documentStore.AsyncDatabaseCommands.ForDatabase(database); generateEntityIdOnTheClient = new GenerateEntityIdOnTheClient(documentStore.Conventions, entity => documentStore.Conventions.GenerateDocumentKeyAsync(database, DatabaseCommands, entity).ResultUnwrap()); Operation = GetBulkInsertOperation(options, DatabaseCommands, changes); entityToJson = new EntityToJson(documentStore, listeners); }
public BulkInsertOperation(string database, IDocumentStore documentStore, DocumentSessionListeners listeners, BulkInsertOptions options, IDatabaseChanges changes) { this.documentStore = documentStore; database = database ?? MultiDatabase.GetDatabaseName(documentStore.Url); // Fitzchak: Should not be ever null because of the above code, please refactor this. DatabaseCommands = database == null ? documentStore.AsyncDatabaseCommands.ForSystemDatabase() : documentStore.AsyncDatabaseCommands.ForDatabase(database); generateEntityIdOnTheClient = new GenerateEntityIdOnTheClient(documentStore, entity => documentStore.Conventions.GenerateDocumentKeyAsync(database, DatabaseCommands, entity).ResultUnwrap()); Operation = GetBulkInsertOperation(options, DatabaseCommands, changes); entityToJson = new EntityToJson(documentStore, listeners); }
internal Subscription(long id, string database, SubscriptionConnectionOptions options, IAsyncDatabaseCommands commands, IDatabaseChanges changes, DocumentConvention conventions, Func <Task> ensureOpenSubscription) { this.id = id; this.options = options; this.commands = commands; this.changes = changes; this.conventions = conventions; this.ensureOpenSubscription = ensureOpenSubscription; if (typeof(T) != typeof(RavenJObject)) { isStronglyTyped = true; generateEntityIdOnTheClient = new GenerateEntityIdOnTheClient(conventions, entity => conventions.GenerateDocumentKeyAsync(database, commands, entity).ResultUnwrap()); } StartWatchingDocs(); StartPullingTask = StartPullingDocs(); }
/// <summary> /// Initializes a new instance of the <see cref="InMemoryDocumentSessionOperations"/> class. /// </summary> protected InMemoryDocumentSessionOperations( string dbName, DocumentStoreBase documentStore, DocumentSessionListeners listeners, Guid id) { Id = id; this.dbName = dbName; this.documentStore = documentStore; this.listeners = listeners; ResourceManagerId = documentStore.ResourceManagerId; UseOptimisticConcurrency = false; AllowNonAuthoritativeInformation = true; NonAuthoritativeInformationTimeout = TimeSpan.FromSeconds(15); MaxNumberOfRequestsPerSession = documentStore.Conventions.MaxNumberOfRequestsPerSession; GenerateEntityIdOnTheClient = new GenerateEntityIdOnTheClient(documentStore, GenerateKey); EntityToJson = new EntityToJson(documentStore, listeners); }
public BulkInsertOperation(string database, IDocumentStore documentStore, DocumentSessionListeners listeners) { this.documentStore = documentStore; database = database ?? MultiDatabase.GetDatabaseName(documentStore.Url); // Fitzchak: Should not be ever null because of the above code, please refactor this. DatabaseCommands = database == null ? documentStore.AsyncDatabaseCommands.ForSystemDatabase() : documentStore.AsyncDatabaseCommands.ForDatabase(database); generateEntityIdOnTheClient = new GenerateEntityIdOnTheClient(documentStore.Conventions, entity => AsyncHelpers.RunSync(() => documentStore.Conventions.GenerateDocumentKeyAsync(database, DatabaseCommands, entity))); // ReSharper disable once VirtualMemberCallInContructor Operation = GetBulkInsertOperation(DatabaseCommands); entityToJson = new EntityToJson(documentStore, listeners); }
internal Subscription(SubscriptionConnectionOptions options, AsyncServerClient commands, DocumentConvention conventions) { _options = options; if (_options.SubscriptionId == 0) { throw new ArgumentException("SubscriptionConnectionOptions must specify the SubscriptionId, but was set to zero.", nameof(options)); } _commands = commands; _conventions = conventions; if (typeof(T) != typeof(RavenJObject)) { _isStronglyTyped = true; _generateEntityIdOnTheClient = new GenerateEntityIdOnTheClient(conventions, entity => { throw new InvalidOperationException("Shouldn't be generating new ids here"); }); } }
/// <summary> /// Updates the batch results. /// </summary> protected void UpdateBatchResults(IList <BatchResult> batchResults, SaveChangesData saveChangesData) { for (var i = saveChangesData.DeferredCommandsCount; i < batchResults.Count; i++) { var batchResult = batchResults[i]; if (batchResult.Method != "PUT") { continue; } var entity = saveChangesData.Entities[i - saveChangesData.DeferredCommandsCount]; DocumentMetadata documentMetadata; if (entitiesAndMetadata.TryGetValue(entity, out documentMetadata) == false) { continue; } batchResult.Metadata["@etag"] = new RavenJValue(batchResult.Etag.ToString()); entitiesByKey[batchResult.Key] = entity; documentMetadata.ETag = batchResult.Etag; documentMetadata.Key = batchResult.Key; documentMetadata.OriginalMetadata = (RavenJObject)batchResult.Metadata.CloneToken(); documentMetadata.Metadata = batchResult.Metadata; documentMetadata.OriginalValue = EntityToJson.ConvertEntityToJson(documentMetadata.Key, entity, documentMetadata.Metadata); GenerateEntityIdOnTheClient.TrySetIdentity(entity, batchResult.Key); foreach (var documentStoreListener in listeners.StoreListeners) { documentStoreListener.AfterStore(batchResult.Key, entity, batchResult.Metadata); } } var lastPut = batchResults.LastOrDefault(x => x.Method == "PUT"); if (lastPut == null) { return; } documentStore.LastEtagHolder.UpdateLastWrittenEtag(lastPut.Etag); }
protected Task <string> GetOrGenerateDocumentKeyAsync(object entity) { string id; GenerateEntityIdOnTheClient.TryGetIdFromInstance(entity, out id); Task <string> generator = id != null ? CompletedTask.With(id) : GenerateKeyAsync(entity); return(generator.ContinueWith(task => { if (task.Result != null && task.Result.StartsWith("/")) { throw new InvalidOperationException("Cannot use value '" + id + "' as a document id because it begins with a '/'"); } return task.Result; })); }
/// <summary> /// Converts the json document to an entity. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="id">The id.</param> /// <param name="documentFound">The document found.</param> /// <param name="metadata">The metadata.</param> /// <returns></returns> protected object ConvertToEntity <T>(string id, RavenJObject documentFound, RavenJObject metadata) { if (typeof(T) == typeof(RavenJObject)) { return((T)(object)documentFound.CloneToken()); } var entity = default(T); EnsureNotReadVetoed(metadata); var documentType = Conventions.GetClrType(id, documentFound, metadata); if (documentType != null) { var type = Type.GetType(documentType); if (type != null) { entity = (T)documentFound.Deserialize(type, Conventions); } } if (Equals(entity, default(T))) { entity = documentFound.Deserialize <T>(Conventions); var document = entity as RavenJObject; if (document != null) { entity = (T)(object)(new DynamicJsonObject(document)); } } GenerateEntityIdOnTheClient.TrySetIdentity(entity, id); foreach (var documentConversionListener in listeners.ConversionListeners) { documentConversionListener.DocumentToEntity(id, entity, documentFound, metadata); } return(entity); }