protected virtual void OnUpdate(Type structureType, object item)
        {
            Ensure.That(item, "item").IsNotNull();

            var implType        = item.GetType();
            var structureSchema = OnUpsertStructureSchema(structureType);
            var structureId     = structureSchema.IdAccessor.GetValue(item);

            if (!structureSchema.HasConcurrencyToken)
            {
                var exists = DbClient.Exists(structureSchema, structureId);
                if (!exists)
                {
                    throw new SisoDbException(ExceptionMessages.WriteSession_NoItemExistsForUpdate.Inject(structureSchema.Name, structureId.Value));
                }
            }
            else
            {
                OnEnsureConcurrencyTokenIsValid(structureSchema, structureId, item, implType);
            }

            CacheConsumeMode = CacheConsumeModes.DoNotUpdateCacheWithDbResult;
            Db.CacheProvider.CleanQueriesFor(structureSchema);
            Db.CacheProvider.Remove(structureSchema, structureId);
            DbClient.DeleteIndexesAndUniquesById(structureId, structureSchema);

            var structureBuilder = Db.StructureBuilders.ResolveBuilderForUpdate(structureSchema);
            var updatedStructure = structureBuilder.CreateStructure(item, structureSchema);

            var bulkInserter = Db.ProviderFactory.GetStructureInserter(DbClient);

            bulkInserter.Replace(structureSchema, updatedStructure);
            InternalEvents.NotifyUpdated(this, structureSchema, updatedStructure, item);
        }
        protected virtual void OnClear(Type structureType)
        {
            Ensure.That(structureType, "structureType").IsNotNull();

            var structureSchema = OnUpsertStructureSchema(structureType);

            CacheConsumeMode = CacheConsumeModes.DoNotUpdateCacheWithDbResult;
            Db.CacheProvider.ClearByType(structureType);

            DbClient.DeleteAll(structureSchema);
        }
        protected virtual void OnDeleteById(Type structureType, object id)
        {
            Ensure.That(id, "id").IsNotNull();

            var structureId     = StructureId.ConvertFrom(id);
            var structureSchema = OnUpsertStructureSchema(structureType);

            CacheConsumeMode = CacheConsumeModes.DoNotUpdateCacheWithDbResult;
            Db.CacheProvider.Remove(structureSchema, structureId);

            DbClient.DeleteById(structureId, structureSchema);
            InternalEvents.NotifyDeleted(this, structureSchema, structureId);
        }
        protected virtual void OnDeleteAllExceptIds(Type structureType, params object[] ids)
        {
            Ensure.That(ids, "ids").HasItems();
            Ensure.That(structureType, "structureType").IsNotNull();

            var structureIds    = ids.Yield().Select(StructureId.ConvertFrom).ToArray();
            var structureSchema = OnUpsertStructureSchema(structureType);

            CacheConsumeMode = CacheConsumeModes.DoNotUpdateCacheWithDbResult;
            Db.CacheProvider.ClearByType(structureType);

            DbClient.DeleteAllExceptIds(structureIds, structureSchema);
        }
        protected virtual void OnDeleteByIds(Type structureType, params object[] ids)
        {
            Ensure.That(ids, "ids").HasItems();
            Ensure.That(structureType, "structureType").IsNotNull();

            var structureIds    = ids.Yield().Select(StructureId.ConvertFrom).ToArray();
            var structureSchema = OnUpsertStructureSchema(structureType);

            CacheConsumeMode = CacheConsumeModes.DoNotUpdateCacheWithDbResult;
            Db.CacheProvider.Remove(structureSchema, new HashSet <IStructureId>(structureIds));

            DbClient.DeleteByIds(structureIds, structureSchema);
            InternalEvents.NotifyDeleted(this, structureSchema, structureIds);
        }
        protected virtual ISession OnUpdate <TContract, TImpl>(object id, Action <TImpl> modifier, Func <TImpl, bool> proceed = null)
            where TContract : class
            where TImpl : class
        {
            Try(() =>
            {
                Ensure.That(id, "id").IsNotNull();
                Ensure.That(modifier, "modifier").IsNotNull();

                var structureSchema = OnUpsertStructureSchema <TContract>();
                var structureId     = StructureId.ConvertFrom(id);

                var existingJson = DbClient.GetJsonByIdWithLock(structureId, structureSchema);

                if (string.IsNullOrWhiteSpace(existingJson))
                {
                    throw new SisoDbException(ExceptionMessages.WriteSession_NoItemExistsForUpdate.Inject(structureSchema.Name, structureId.Value));
                }

                var item = Db.Serializer.Deserialize <TImpl>(existingJson);

                modifier.Invoke(item);
                if (proceed != null && !proceed.Invoke(item))
                {
                    return;
                }

                if (structureSchema.HasConcurrencyToken)
                {
                    OnEnsureConcurrencyTokenIsValid(structureSchema, structureId, item, typeof(TImpl));
                }

                CacheConsumeMode = CacheConsumeModes.DoNotUpdateCacheWithDbResult;
                Db.CacheProvider.CleanQueriesFor(structureSchema);
                Db.CacheProvider.Remove(structureSchema, structureId);
                DbClient.DeleteIndexesAndUniquesById(structureId, structureSchema);

                var structureBuilder = Db.StructureBuilders.ResolveBuilderForUpdate(structureSchema);
                var updatedStructure = structureBuilder.CreateStructure(item, structureSchema);

                var bulkInserter = Db.ProviderFactory.GetStructureInserter(DbClient);
                bulkInserter.Replace(structureSchema, updatedStructure);
                InternalEvents.NotifyUpdated(this, structureSchema, updatedStructure, item);
            });

            return(this);
        }
        protected DbSession(ISisoDatabase db)
        {
            Ensure.That(db, "db").IsNotNull();

            _id                  = Guid.NewGuid();
            _db                  = db;
            DbClient             = Db.ProviderFactory.GetTransactionalDbClient(Db);
            ExecutionContext     = new SessionExecutionContext(this);
            Status               = SessionStatus.Active;
            InternalEvents       = new SessionEvents();
            SqlStatements        = Db.ProviderFactory.GetSqlStatements();
            QueryGenerator       = Db.ProviderFactory.GetDbQueryGenerator();
            SqlExpressionBuilder = Db.ProviderFactory.GetSqlExpressionBuilder();
            _queryEngine         = new DbQueryEngine(ExecutionContext, QueryGenerator);
            _advanced            = new DbSessionAdvanced(ExecutionContext, QueryGenerator, SqlExpressionBuilder);
            CacheConsumeMode     = CacheConsumeModes.UpdateCacheWithDbResult;
        }
        protected virtual void OnInsert(Type structureType, object item)
        {
            Ensure.That(structureType, "structureType").IsNotNull();
            Ensure.That(item, "item").IsNotNull();

            var structureSchema = OnUpsertStructureSchema(structureType);

            CacheConsumeMode = CacheConsumeModes.DoNotUpdateCacheWithDbResult;
            Db.CacheProvider.CleanQueriesFor(structureSchema);

            var structureBuilder = Db.StructureBuilders.ResolveBuilderForInsert(structureSchema, DbClient);
            var structure        = structureBuilder.CreateStructure(item, structureSchema);

            var structureInserter = Db.ProviderFactory.GetStructureInserter(DbClient);

            structureInserter.Insert(structureSchema, new[] { structure });
            InternalEvents.NotifyInserted(this, structureSchema, structure, item);
        }
        protected virtual void OnInsertManyJson(Type structureType, IEnumerable <string> json)
        {
            Ensure.That(json, "json").IsNotNull();

            var structureSchema = OnUpsertStructureSchema(structureType);

            CacheConsumeMode = CacheConsumeModes.DoNotUpdateCacheWithDbResult;
            Db.CacheProvider.CleanQueriesFor(structureSchema);

            var structureBuilder  = Db.StructureBuilders.ResolveBuilderForInsert(structureSchema, DbClient);
            var structureInserter = Db.ProviderFactory.GetStructureInserter(DbClient);

            foreach (var itemsBatch in Db.Serializer.DeserializeMany(json, structureSchema.Type.Type).Batch(Db.Settings.MaxInsertManyBatchSize))
            {
                var structures = structureBuilder.CreateStructures(itemsBatch, structureSchema);
                structureInserter.Insert(structureSchema, structures);
                InternalEvents.NotifyInserted(this, structureSchema, structures, itemsBatch);
            }
        }
示例#10
0
        protected virtual void OnDeleteByQuery <T>(Expression <Func <T, bool> > predicate) where T : class
        {
            Ensure.That(predicate, "predicate").IsNotNull();

            CacheConsumeMode = CacheConsumeModes.DoNotUpdateCacheWithDbResult;

            var structureSchema = OnUpsertStructureSchema <T>();

            Db.CacheProvider.ClearByType(structureSchema);

            var queryBuilder = Db.ProviderFactory.GetQueryBuilder <T>(Db.StructureSchemas);

            queryBuilder.Where(predicate);

            var query = queryBuilder.Build();
            var sql   = QueryGenerator.GenerateQueryReturningStrutureIds(query);

            DbClient.DeleteByQuery(sql, structureSchema);
            InternalEvents.NotifyDeleted(this, structureSchema, query);
        }
示例#11
0
        protected virtual string OnInsertJson(Type structureType, string json)
        {
            Ensure.That(json, "json").IsNotNullOrWhiteSpace();

            var structureSchema = OnUpsertStructureSchema(structureType);

            CacheConsumeMode = CacheConsumeModes.DoNotUpdateCacheWithDbResult;
            Db.CacheProvider.CleanQueriesFor(structureSchema);

            var item             = Db.Serializer.Deserialize(json, structureType);
            var structureBuilder = Db.StructureBuilders.ResolveBuilderForInsert(structureSchema, DbClient);
            var structure        = structureBuilder.CreateStructure(item, structureSchema);

            var structureInserter = Db.ProviderFactory.GetStructureInserter(DbClient);

            structureInserter.Insert(structureSchema, new[] { structure });
            InternalEvents.NotifyInserted(this, structureSchema, structure, item);

            return(structure.Data);
        }
        public static T Consume <T>(this ICacheProvider cacheProvider, IStructureSchema structureSchema, Expression <Func <T, bool> > predicate, Func <Expression <Func <T, bool> >, T> nonCacheQuery, CacheConsumeModes consumeMode) where T : class
        {
            if (!cacheProvider.IsEnabledFor(structureSchema))
            {
                return(nonCacheQuery.Invoke(predicate));
            }

            var cache     = cacheProvider[structureSchema.Type.Type];
            var structure = cache.Query(predicate).SingleOrDefault();

            if (structure != null)
            {
                return(structure);
            }

            structure = nonCacheQuery.Invoke(predicate);
            if (structure == null || consumeMode == CacheConsumeModes.DoNotUpdateCacheWithDbResult)
            {
                return(structure);
            }

            return(cacheProvider[structureSchema.Type.Type].Put(structureSchema.IdAccessor.GetValue(structure), structure));
        }
        public static IEnumerable <T> Consume <T>(this ICacheProvider cacheProvider, IStructureSchema structureSchema, IDbQuery query, Func <IDbQuery, IEnumerable <T> > nonCacheQuery, CacheConsumeModes consumeMode) where T : class
        {
            if (!cacheProvider.IsEnabledFor(structureSchema))
            {
                return(nonCacheQuery.Invoke(query));
            }

            var queryChecksum = DbQueryChecksumGenerator.Instance.Generate(query);
            var cache         = cacheProvider[structureSchema.Type.Type];

            if (cache.HasQuery(queryChecksum))
            {
                return(cache.GetByQuery <T>(queryChecksum));
            }

            if (!query.IsCacheable || consumeMode == CacheConsumeModes.DoNotUpdateCacheWithDbResult)
            {
                return(nonCacheQuery.Invoke(query));
            }

            return(cache.Put(
                       queryChecksum,
                       nonCacheQuery.Invoke(query).Select(s => new KeyValuePair <IStructureId, T>(structureSchema.IdAccessor.GetValue(s), s))));
        }
        public static IEnumerable <T> Consume <T>(this ICacheProvider cacheProvider, IStructureSchema structureSchema, IStructureId[] structureIds, Func <IStructureId[], IEnumerable <T> > nonCacheQuery, CacheConsumeModes consumeMode) where T : class
        {
            if (!cacheProvider.IsEnabledFor(structureSchema))
            {
                return(nonCacheQuery.Invoke(structureIds));
            }

            var cache        = cacheProvider[structureSchema.Type.Type];
            var cachedResult = cache.GetByIds <T>(structureIds).ToDictionary(kv => kv.Key, kv => kv.Value); //Ok to turn it to in-mem rep and not yield. GetByIds, should not be enormous resultset.

            if (!cachedResult.Any())
            {
                if (consumeMode == CacheConsumeModes.DoNotUpdateCacheWithDbResult)
                {
                    return(nonCacheQuery.Invoke(structureIds));
                }

                return(cache.Put(nonCacheQuery.Invoke(structureIds).Select(s => new KeyValuePair <IStructureId, T>(structureSchema.IdAccessor.GetValue(s), s))));
            }

            var allWasCached = cachedResult.Count == structureIds.Length;

            if (allWasCached)
            {
                return(cachedResult.Values);
            }

            var deltaIds = structureIds.Where(sid => !cachedResult.ContainsKey(sid)).ToArray();

            if (!deltaIds.Any())
            {
                return(cachedResult.Values);
            }

            if (consumeMode == CacheConsumeModes.DoNotUpdateCacheWithDbResult)
            {
                return(cachedResult.Values.MergeWith(nonCacheQuery.Invoke(deltaIds)));
            }

            return(cachedResult.Values.MergeWith(cache.Put(nonCacheQuery.Invoke(deltaIds).Select(s => new KeyValuePair <IStructureId, T>(structureSchema.IdAccessor.GetValue(s), s)))));
        }
        public static T Consume <T>(this ICacheProvider cacheProvider, IStructureSchema structureSchema, IStructureId structureId, Func <IStructureId, T> nonCacheQuery, CacheConsumeModes consumeMode) where T : class
        {
            if (!cacheProvider.IsEnabledFor(structureSchema))
            {
                return(nonCacheQuery.Invoke(structureId));
            }

            var cache     = cacheProvider[structureSchema.Type.Type];
            var structure = cache.GetById <T>(structureId);

            if (structure != null)
            {
                return(structure);
            }

            structure = nonCacheQuery.Invoke(structureId);
            if (structure == null || consumeMode == CacheConsumeModes.DoNotUpdateCacheWithDbResult)
            {
                return(structure);
            }

            return(cache.Put(structureId, structure));
        }
示例#16
0
        public virtual ISession UpdateMany <T>(Expression <Func <T, bool> > predicate, Action <T> modifier) where T : class
        {
            Try(() =>
            {
                Ensure.That(predicate, "predicate").IsNotNull();
                Ensure.That(modifier, "modifier").IsNotNull();

                var structureSchema = OnUpsertStructureSchema <T>();
                CacheConsumeMode    = CacheConsumeModes.DoNotUpdateCacheWithDbResult;
                Db.CacheProvider.CleanQueriesFor(structureSchema);

                var deleteIds         = new HashSet <IStructureId>();
                var keepQueue         = new List <T>(Db.Settings.MaxUpdateManyBatchSize);
                var structureBuilder  = Db.StructureBuilders.ResolveBuilderForUpdate(structureSchema);
                var structureInserter = Db.ProviderFactory.GetStructureInserter(DbClient);
                var queryBuilder      = Db.ProviderFactory.GetQueryBuilder <T>(Db.StructureSchemas);
                var query             = queryBuilder.Where(predicate).Build();
                var sqlQuery          = QueryGenerator.GenerateQuery(query);

                foreach (var structure in Db.Serializer.DeserializeMany <T>(
                             DbClient.ReadJson(structureSchema, sqlQuery.Sql, sqlQuery.Parameters)))
                {
                    var structureIdBefore = structureSchema.IdAccessor.GetValue(structure);
                    modifier.Invoke(structure);
                    var structureIdAfter = structureSchema.IdAccessor.GetValue(structure);

                    if (!structureIdBefore.Value.Equals(structureIdAfter.Value))
                    {
                        throw new SisoDbException(ExceptionMessages.WriteSession_UpdateMany_NewIdDoesNotMatchOldId.Inject(
                                                      structureIdAfter.Value, structureIdBefore.Value));
                    }

                    deleteIds.Add(structureIdBefore);

                    keepQueue.Add(structure);
                    if (keepQueue.Count < Db.Settings.MaxUpdateManyBatchSize)
                    {
                        continue;
                    }

                    Db.CacheProvider.Remove(structureSchema, deleteIds);
                    DbClient.DeleteByIds(deleteIds, structureSchema);
                    deleteIds.Clear();

                    var items      = keepQueue.ToArray();
                    var structures = structureBuilder.CreateStructures(items, structureSchema);
                    structureInserter.Insert(structureSchema, structures);
                    keepQueue.Clear();
                    InternalEvents.NotifyUpdated(this, structureSchema, structures, items);
                }

                if (keepQueue.Count > 0)
                {
                    Db.CacheProvider.Remove(structureSchema, deleteIds);
                    DbClient.DeleteByIds(deleteIds, structureSchema);
                    deleteIds.Clear();

                    var items      = keepQueue.ToArray();
                    var structures = structureBuilder.CreateStructures(items, structureSchema);
                    structureInserter.Insert(structureSchema, structures);
                    keepQueue.Clear();
                    InternalEvents.NotifyUpdated(this, structureSchema, structures, items);
                }
            });

            return(this);
        }