Example #1
0
        /// <summary>
        /// Begins the async load operation
        /// </summary>
        /// <param name="id">The id.</param>
        /// <param name="token">The canecllation token.</param>
        /// <returns></returns>
        public async Task <T> LoadAsync <T>(string id, CancellationToken token = default(CancellationToken))
        {
            if (id == null)
            {
                throw new ArgumentNullException("id", "The document id cannot be null");
            }
            object entity;

            if (EntitiesById.TryGetValue(id, out entity))
            {
                return((T)entity);
            }
            JsonDocument value;

            if (includedDocumentsByKey.TryGetValue(id, out value))
            {
                includedDocumentsByKey.Remove(id);
                return(TrackEntity <T>(value));
            }
            if (IsDeleted(id))
            {
                return(default(T));
            }

            IncrementRequestCount();
            var loadOperation = new LoadOperation(this, AsyncDatabaseCommands.DisableAllCaching, id);

            return(await CompleteLoadAsync <T>(id, loadOperation, token).ConfigureAwait(false));
        }
Example #2
0
        /// <summary>
        ///     Return the entity by it's id
        /// </summary>
        /// <param name="entityId"></param>
        /// <returns></returns>
        public DirectEntity GetEntityById(long entityId)
        {
            DirectEntity entity;

            if (EntitiesById.TryGetValue(entityId, out entity))
            {
                return(entity);
            }

            return(null);
        }
Example #3
0
        public T Load <T>(string id)
        {
            object existingEntity;

            if (EntitiesById.TryGetValue(id, out existingEntity))
            {
                return((T)existingEntity);
            }

            IncrementRequestCount();
            var shardRequestData = new ShardRequestData
            {
                EntityType = typeof(T),
                Keys       = { id }
            };
            var dbCommands = GetCommandsToOperateOn(shardRequestData);
            var results    = shardStrategy.ShardAccessStrategy.Apply(dbCommands, shardRequestData, (commands, i) =>
            {
                var loadOperation = new LoadOperation(this, commands.DisableAllCaching, id);
                bool retry;
                do
                {
                    loadOperation.LogOperation();
                    using (loadOperation.EnterLoadContext())
                    {
                        retry = loadOperation.SetResult(commands.Get(id));
                    }
                } while (retry);
                return(loadOperation.Complete <T>().FirstOrDefault());
            });

            var shardsContainThisDocument = results.Where(x => !Equals(x, default(T))).ToArray();

            if (shardsContainThisDocument.Length > 1)
            {
                throw new InvalidOperationException("Found document with id: " + id +
                                                    " on more than a single shard, which is not allowed. Document keys have to be unique cluster-wide.");
            }

            return(shardsContainThisDocument.FirstOrDefault());
        }
Example #4
0
        /// <summary>
        /// Loads the specified entity with the specified id.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public T Load <T>(string id)
        {
            if (id == null)
            {
                throw new ArgumentNullException("id", "The document id cannot be null");
            }
            if (IsDeleted(id))
            {
                return(default(T));
            }
            object existingEntity;

            if (EntitiesById.TryGetValue(id, out existingEntity))
            {
                return((T)existingEntity);
            }
            JsonDocument value;

            if (includedDocumentsByKey.TryGetValue(id, out value))
            {
                includedDocumentsByKey.Remove(id);
                return(TrackEntity <T>(value));
            }

            IncrementRequestCount();
            var  loadOperation = new LoadOperation(this, DatabaseCommands.DisableAllCaching, id);
            bool retry;

            do
            {
                loadOperation.LogOperation();
                using (loadOperation.EnterLoadContext())
                {
                    retry = loadOperation.SetResult(DatabaseCommands.Get(id));
                }
            } while (retry);
            return(loadOperation.Complete <T>().FirstOrDefault());
        }
Example #5
0
        public T[] LoadInternal <T>(string[] ids, KeyValuePair <string, Type>[] includes)
        {
            var results      = new T[ids.Length];
            var includePaths = includes != null?includes.Select(x => x.Key).ToArray() : null;

            var idsToLoad = GetIdsThatNeedLoading <T>(ids, includePaths, transformer: null);

            if (!idsToLoad.Any())
            {
                return(results);
            }

            IncrementRequestCount();

            foreach (var shard in idsToLoad)
            {
                var currentShardIds     = shard.Select(x => x.Id).ToArray();
                var multiLoadOperations = shardStrategy.ShardAccessStrategy.Apply(shard.Key, new ShardRequestData
                {
                    EntityType = typeof(T),
                    Keys       = currentShardIds.ToList()
                }, (dbCmd, i) =>
                {
                    var multiLoadOperation = new LoadOperation(this, dbCmd.DisableAllCaching, currentShardIds, includes);
                    LoadResult loadResult;
                    do
                    {
                        multiLoadOperation.LogOperation();
                        using (multiLoadOperation.EnterLoadContext())
                        {
                            loadResult = dbCmd.Get(currentShardIds, includePaths);
                        }
                    } while (multiLoadOperation.SetResult(loadResult));
                    return(multiLoadOperation);
                });
                foreach (var multiLoadOperation in multiLoadOperations)
                {
                    var loadResults = multiLoadOperation.Complete <T>();
                    for (int i = 0; i < loadResults.Length; i++)
                    {
                        if (ReferenceEquals(loadResults[i], null))
                        {
                            continue;
                        }
                        var id           = currentShardIds[i];
                        var itemPosition = Array.IndexOf(ids, id);
                        if (ReferenceEquals(results[itemPosition], default(T)) == false)
                        {
                            throw new InvalidOperationException("Found document with id: " + id +
                                                                " on more than a single shard, which is not allowed. Document keys have to be unique cluster-wide.");
                        }
                        results[itemPosition] = loadResults[i];
                    }
                }
            }
            return(ids.Select(id => // so we get items that were skipped because they are already in the session cache
            {
                object val;
                EntitiesById.TryGetValue(id, out val);
                return (T)val;
            }).ToArray());
        }
Example #6
0
        public Task <T> LoadAsync <T>(string id, CancellationToken token = default(CancellationToken))
        {
            if (KnownMissingIds.Contains(id))
            {
                return(CompletedTask.With(default(T)));
            }

            object existingEntity;

            if (EntitiesById.TryGetValue(id, out existingEntity))
            {
                return(CompletedTask.With((T)existingEntity));
            }


            IncrementRequestCount();
            var shardRequestData = new ShardRequestData
            {
                EntityType = typeof(T),
                Keys       = { id }
            };

            var dbCommands = GetCommandsToOperateOn(shardRequestData);
            var results    = shardStrategy.ShardAccessStrategy.ApplyAsync(dbCommands, shardRequestData, (commands, i) =>
            {
                var loadOperation = new LoadOperation(this, commands.DisableAllCaching, id);

                Func <Task> executer = null;
                executer             = () =>
                {
                    loadOperation.LogOperation();

                    var loadContext = loadOperation.EnterLoadContext();
                    return(commands.GetAsync(id, token: token).ContinueWith(task =>
                    {
                        if (loadContext != null)
                        {
                            loadContext.Dispose();
                        }

                        if (loadOperation.SetResult(task.Result))
                        {
                            return executer();
                        }
                        return new CompletedTask();
                    }).Unwrap());
                };
                return(executer().ContinueWith(_ =>
                {
                    _.AssertNotFailed();
                    return loadOperation.Complete <T>();
                }).WithCancellation(token));
            });

            return(results.ContinueWith(task =>
            {
                var shardsContainThisDocument = task.Result.Select(arg => arg.FirstOrDefault()).Where(x => !Equals(x, default(T))).ToArray();
                if (shardsContainThisDocument.Count() > 1)
                {
                    throw new InvalidOperationException("Found document with id: " + id +
                                                        " on more than a single shard, which is not allowed. Document keys have to be unique cluster-wide.");
                }

                return shardsContainThisDocument.FirstOrDefault();
            }).WithCancellation(token));
        }