コード例 #1
0
ファイル: GameOrderCaching.cs プロジェクト: haositongxue/avia
        /// <summary>
        /// 生产订单采集任务(右进)
        /// 同步生产延迟任务
        /// </summary>
        /// <param name="gameCode">游戏代码</param>
        /// <returns>写入队列是否成功</returns>
        public bool SaveTask(string gameCode)
        {
            string taskKey = $"{TASKID}{gameCode}";
            bool   success = false;

            // 常规任务
            if (!this.NewExecutor().KeyExists(taskKey))
            {
                IBatch batch = this.NewExecutor().CreateBatch();
                batch.ListRightPushAsync(TASK, new OrderTaskModel(gameCode, MarkType.Normal));
                // 为了防止任务发生死锁,5分钟没有得到执行则抛弃
                batch.StringSetAsync(taskKey, OrderTaskStatus.Wait.GetRedisValue(), TimeSpan.FromMinutes(5));
                batch.Execute();
                success = true;
            }

            string delayKey = $"{TASKDELAY}{gameCode}";

            // 延迟任务
            if (!this.NewExecutor().KeyExists(delayKey))
            {
                IBatch batch = this.NewExecutor().CreateBatch();
                batch.ListRightPushAsync(TASK, new OrderTaskModel(gameCode, MarkType.Delay));
                // 延迟任务60分钟执行一次(只能等待过期删除)
                batch.StringSetAsync(delayKey, OrderTaskStatus.Wait.GetRedisValue(), TimeSpan.FromMinutes(60));
                batch.Execute();
                success = true;
            }

            return(success);
        }
コード例 #2
0
        /// <summary>
        /// Writes the version out for the entity key
        /// </summary>
        /// <param name="transform"></param>
        /// <param name="key"></param>
        /// <param name="version"></param>
        /// <param name="expiry"></param>
        /// <returns></returns>
        public override async Task <bool> WriteVersion(EntityTransformHolder <K, E> transform, K key, string version, TimeSpan?expiry = null)
        {
            if (transform == null)
            {
                throw new ArgumentNullException(nameof(transform), "The EntityTransformHolder cannot be null.");
            }

            try
            {
                IDatabase rDb     = mLazyConnection.Value.GetDatabase();
                IBatch    batch   = rDb.CreateBatch();
                RedisKey  hashkey = RedisKeyGet(transform, key);

                var tasks = new List <Task>
                {
                    //Version
                    batch.HashSetAsync(hashkey, cnKeyVersion, version, when: When.Always),
                    // Expiry
                    batch.KeyExpireAsync(hashkey, expiry ?? mEntityTtl)
                };
                batch.Execute();

                await Task.WhenAll(tasks);

                return(true);
            }
            catch (Exception)
            {
                // Don't raise an exception here
            }
            return(false);
        }
コード例 #3
0
        private void DoTask()
        {
            try
            {
                _batchConfig.SetSchedulerTime(DateTime.Now);
                _batch.SetBatchConfig(_batchConfig);
                _batch.Prepare();
                while (_isRunning)
                {
                    if (!_batch.IsRun())
                    {
                        return;
                    }

                    Log.Info($"{_batchConfig.BatchName}当前执行{_batchConfig.SchedulerTime}");

                    _batch.Execute();
                    _batch.Clear();
                    Log.Info($"{_batchConfig.BatchName}执行完成{_batchConfig.SchedulerTime}");
                    _batch.UpdateTimeStamp(_timeSpan);
                    Thread.Sleep(_timeSpan);
                }
            }
            catch (Exception ex)
            {
                EmailErr(new AggregateException("执行错误", ex));
            }
        }
コード例 #4
0
        /// <inheritDoc cref="INotificationPlugin.GetCurrentNotifications" />
        public IList <Notification> GetCurrentNotifications(string accountId)
        {
            IList <Task <HashEntry[]> > responses = new List <Task <HashEntry[]> >();

            var redis = redisConnector.GetResource();
            var guids = redis.ListRange("notifs:" + accountId, 0, -1);

            //----- we are using batch to avoid roundtrips
            IBatch batch = redis.CreateBatch();

            foreach (string guid in guids)
            {
                var hgetPending = batch.HashGetAllAsync("notif:" + guid);
                responses.Add(hgetPending);
            }

            batch.Execute();
            batch.WaitAll(responses.ToArray());

            List <Notification> notifications = new List <Notification>();

            foreach (Task <HashEntry[]> response in responses)
            {
                if (response.IsCompleted && response.Result.Any())
                {
                    notifications.Add(HashEntryToNotification(response.Result));
                }
            }

            return(notifications);
        }
コード例 #5
0
        static void Main(string[] args)
        {
            var redis = RedisStore.RedisCache;

            RedisKey alphaKey = "alphaKey";
            RedisKey betaKey  = "betaKey";

            redis.KeyDelete(alphaKey, CommandFlags.FireAndForget);
            redis.KeyDelete(betaKey, CommandFlags.FireAndForget);

            var writeTask     = redis.StringSetAsync(alphaKey, "abc");
            var writeBetaTask = redis.StringSetAsync(betaKey, "beta");

            var readTask = redis.StringGetAsync(alphaKey);

            redis.Wait(writeTask);

            var readValue = redis.Wait(readTask);

            Console.WriteLine($"Redis Task wait and read {readValue}");

            writeBetaTask.Wait();

            readValue = redis.StringGet(betaKey);

            Console.WriteLine($"Task wait and read {readValue}");


            //Batching
            var list = new List <Task <bool> >();
            var keys = new List <RedisKey> {
                alphaKey, betaKey
            };
            IBatch batch = redis.CreateBatch();

            //add the delete into batch
            batch.KeyDeleteAsync(alphaKey);

            foreach (var key in keys)
            {
                var task = batch.StringSetAsync(key, "123");
                list.Add(task);
            }

            batch.Execute();

            Task.WhenAll(list.ToArray());

            readTask  = redis.StringGetAsync(alphaKey);
            readValue = redis.Wait(readTask);
            Console.WriteLine($"Alpha read value {readValue}");


            readTask  = redis.StringGetAsync(betaKey);
            readValue = redis.Wait(readTask);
            Console.WriteLine($"Beta read value {readValue}");


            Console.ReadKey();
        }
コード例 #6
0
        /// <summary>
        /// Gets the structure of a source
        /// </summary>
        /// <param name="Source">Source to use</param>
        /// <returns>The source structure</returns>
        public ISource GetSourceStructure(ISourceInfo Source)
        {
            string      DatabaseName   = Regex.Match(Source.Connection, "Initial Catalog=(.*?;)").Value.Replace("Initial Catalog=", "").Replace(";", "");
            ISourceInfo DatabaseSource = SourceProvider.GetSource(Regex.Replace(Source.Connection, "Initial Catalog=(.*?;)", ""));

            if (!SourceExists(DatabaseName, DatabaseSource))
            {
                return(null);
            }
            var    Temp  = new Database(DatabaseName);
            IBatch Batch = Provider.Batch(Source);

            IBuilder[] Builders =
            {
                new Tables(),
                new TableColumns(),
                new TableTriggers(),
                new TableForeignKeys(),
                new Views(),
                new StoredProcedures(),
                new StoredProcedureColumns(),
                new Functions()
            };
            Builders.ForEach(x => x.GetCommand(Batch));
            var Results = Batch.Execute();

            Builders.For(0, Builders.Length - 1, (x, y) => y.FillDatabase(Results[x], Temp));
            return(Temp);
        }
コード例 #7
0
        /// <summary>
        /// This method writes out the references for the entity.
        /// </summary>
        /// <param name="transform">The entity transform.</param>
        /// <param name="reference">The reference.</param>
        /// <param name="key">The root key.</param>
        /// <param name="version">The entity version.</param>
        /// <param name="expiry">Optional expiry timespan for the key</param>
        /// <returns>Returns an async task.</returns>
        public override async Task <bool> WriteReference(EntityTransformHolder <K, E> transform, Tuple <string, string> reference, K key, string version, TimeSpan?expiry = null)
        {
            if (transform == null)
            {
                throw new ArgumentNullException(nameof(transform), "The EntityTransformHolder cannot be null.");
            }

            try
            {
                IDatabase rDb   = mLazyConnection.Value.GetDatabase();
                IBatch    batch = rDb.CreateBatch();
                var       tasks = new List <Task>(WriteReference(batch, transform, reference, key, version, expiry));
                batch.Execute();

                await Task.WhenAll(tasks);

                return(true);
            }
            catch (Exception)
            {
                // Don't raise an exception here
            }

            return(false);
        }
コード例 #8
0
        public uint CreateTag(IBatch <T> batch, Tag tag, uint entityId)
        {
            var result = batch.Execute(GetInsertTagStep(tag, entityId));

            uint id = 0;

            return((result != null && uint.TryParse(result.ToString(), out id)) ? id : 0);
        }
コード例 #9
0
ファイル: ViewCaching.cs プロジェクト: haositongxue/avia
        /// <summary>
        /// 保存全名
        /// </summary>
        /// <param name="fullName"></param>
        /// <param name="viewId"></param>
        public void SaveViewID(string fullName, int viewId)
        {
            IBatch batch = this.NewExecutor().CreateBatch();

            batch.HashSetAsync(VIEWID, fullName, viewId.GetRedisValue());
            batch.HashSetAsync(VIEWCODE, viewId.GetRedisValue(), fullName);
            batch.Execute();
        }
コード例 #10
0
        public uint CreateEntity(IBatch <T> batch, T entity)
        {
            var result = batch.Execute(GetInsertEntityStep(entity));

            uint id = 0;

            return((result != null && uint.TryParse(result.ToString(), out id)) ? id : 0);
        }
コード例 #11
0
        public uint CreateLink(IBatch <T> batch, Link link, uint entityId)
        {
            var result = batch.Execute(GetInsertLinkStep(link, entityId));

            uint id = 0;

            return((result != null && uint.TryParse(result.ToString(), out id)) ? id : 0);
        }
        public void Batch()
        {
            var    Temp  = new Utilities.ORM.Manager.QueryProvider.Default.SQLServer.SQLServerQueryProvider();
            IBatch Batch = Temp.Batch(TestDatabaseSource);

            Assert.Equal(0, Batch.CommandCount);
            Assert.Equal(0, Batch.Execute().First().Count());
            Assert.Equal(typeof(Utilities.ORM.Manager.QueryProvider.Default.DatabaseBatch), Batch.GetType());
        }
コード例 #13
0
ファイル: RedisUtils.cs プロジェクト: IMAXZ/Utils
        /// <summary>
        /// 批量添加hash
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dic"></param>
        public static void HashSetBatch(string key, Dictionary <string, string> dic)
        {
            IBatch batch = Db.CreateBatch();

            foreach (var item in dic)
            {
                batch.HashSetAsync(key, item.Key, item.Value);
            }
            batch.Execute();
        }
コード例 #14
0
        /// <summary>
        /// Sets up the specified database schema
        /// </summary>
        /// <param name="Mappings">The mappings.</param>
        /// <param name="Database">The database.</param>
        /// <param name="QueryProvider">The query provider.</param>
        public void Setup(ListMapping <IDatabase, IMapping> Mappings, IDatabase Database, QueryProvider.Manager QueryProvider)
        {
            ISourceInfo TempSource   = SourceProvider.GetSource(Database.Name);
            var         TempDatabase = new Schema.Default.Database.Database(Regex.Match(TempSource.Connection, "Initial Catalog=(.*?;)").Value.Replace("Initial Catalog=", "").Replace(";", ""));

            SetupTables(Mappings, Database, TempDatabase);
            SetupJoiningTables(Mappings, Database, TempDatabase);
            SetupAuditTables(Database, TempDatabase);

            foreach (ITable Table in TempDatabase.Tables)
            {
                Table.SetupForeignKeys();
            }
            List <string> Commands = GenerateSchema(TempDatabase, SourceProvider.GetSource(Database.Name)).ToList();
            IBatch        Batch    = QueryProvider.Batch(SourceProvider.GetSource(Database.Name));

            for (int x = 0; x < Commands.Count; ++x)
            {
                if (Commands[x].ToUpperInvariant().Contains("CREATE DATABASE"))
                {
                    QueryProvider.Batch(SourceProvider.GetSource(Regex.Replace(SourceProvider.GetSource(Database.Name).Connection, "Initial Catalog=(.*?;)", ""))).AddCommand(null, null, CommandType.Text, Commands[x]).Execute();
                }
                else if (Commands[x].Contains("CREATE TRIGGER") || Commands[x].Contains("CREATE FUNCTION"))
                {
                    if (Batch.CommandCount > 0)
                    {
                        Batch.Execute();
                        Batch = QueryProvider.Batch(SourceProvider.GetSource(Database.Name));
                    }
                    Batch.AddCommand(null, null, CommandType.Text, Commands[x]);
                    if (x < Commands.Count - 1)
                    {
                        Batch.Execute();
                        Batch = QueryProvider.Batch(SourceProvider.GetSource(Database.Name));
                    }
                }
                else
                {
                    Batch.AddCommand(null, null, CommandType.Text, Commands[x]);
                }
            }
            Batch.Execute();
        }
コード例 #15
0
ファイル: RedisUtils.cs プロジェクト: IMAXZ/Utils
        public static void ListRightPushBatch(string key, List <string> list)
        {
            IBatch batch = Db.CreateBatch();

            foreach (var item in list)
            {
                batch.ListRightPushAsync(key, item);
            }
            batch.Execute();
        }
コード例 #16
0
        public void ExecuteBatch()
        {
            if (!_batchInProgress)
            {
                throw new InvalidOperationException("You must create a batch before executing it!");
            }

            _batch.Execute();
            _batchInProgress = false;
            _batch           = null;
        }
コード例 #17
0
ファイル: Program.cs プロジェクト: z808089/NoSQL
        //一次性插入多种不同类型的数据到Redis数据库
        public static void InsertByBatch(IDatabase db)
        {
            IBatch batch = db.CreateBatch();

            db.SetAdd("A", "a");
            db.ListRightPush("listTest1", "shanzm");
            //db.GeoAdd("ShopsGeo1", new GeoEntry(116.34039, 39.94218, "1"));
            //连接Redis服务器把上面的所有操作,一次性执行
            //CreateBatch()、Execute()之间的操作一次性提交给服务器
            batch.Execute();
        }
コード例 #18
0
 /// <summary>
 /// 调度框架使用
 /// </summary>
 /// <param name="batch"></param>
 /// <param name="config"></param>
 public static void RunBatch(IBatch batch, BatchConfig config)
 {
     batch.SetBatchConfig(config);
     if (!batch.IsRun())
     {
         return;
     }
     batch.Prepare();
     batch.Execute();
     batch.Clear();
 }
コード例 #19
0
ファイル: SiteCaching.cs プロジェクト: haositongxue/avia
        /// <summary>
        /// 保存白名单IP
        /// </summary>
        /// <param name="siteId"></param>
        /// <param name="iplist"></param>
        public void SaveWhiteIP(int siteId, IEnumerable <string> iplist)
        {
            string key   = $"{WHITEIP}{siteId}";
            IBatch batch = this.NewExecutor().CreateBatch(key);

            batch.KeyDeleteAsync(key);
            foreach (string ip in iplist)
            {
                batch.SetAddAsync(key, ip);
            }
            batch.Execute();
        }
コード例 #20
0
ファイル: AdminCaching.cs プロジェクト: haositongxue/avia
        /// <summary>
        /// 保存管理员权限
        /// </summary>
        /// <param name="adminId"></param>
        /// <param name="permissions"></param>
        public void SavePermission(int adminId, params string[] permissions)
        {
            string key   = $"{PERMISSION}{adminId}";
            IBatch batch = this.NewExecutor().CreateBatch();

            batch.KeyDeleteAsync(key);
            foreach (string permission in permissions)
            {
                batch.SetAddAsync(key, permission);
            }
            batch.Execute();
        }
コード例 #21
0
 /// <summary>
 /// Saves an object to the database
 /// </summary>
 /// <typeparam name="ObjectType">Object type</typeparam>
 /// <typeparam name="PrimaryKeyType">Primary key type</typeparam>
 /// <param name="Object">Object to save</param>
 public void Save <ObjectType, PrimaryKeyType>(ObjectType Object)
     where ObjectType : class
 {
     Cache.RemoveByTag(typeof(ObjectType).GetName());
     foreach (ISourceInfo Source in SourceProvider.Where(x => x.Writable).OrderBy(x => x.Order))
     {
         IMapping Mapping = MapperProvider[typeof(ObjectType), Source];
         if (Mapping != null)
         {
             IGenerator <ObjectType> Generator = QueryProvider.Generate <ObjectType>(Source, MapperProvider[typeof(ObjectType), Source], MapperProvider.GetStructure(Mapping.DatabaseConfigType));
             IBatch TempBatch = QueryProvider.Batch(Source);
             CascadeSave <ObjectType>(Object, Source, Mapping, TempBatch, new List <object>());
             TempBatch.Execute();
             TempBatch = QueryProvider.Batch(Source);
             TempBatch.AddCommand(Generator.Save <PrimaryKeyType>(Object));
             TempBatch.Execute();
             TempBatch = QueryProvider.Batch(Source);
             JoinsDelete <ObjectType>(Object, Source, Mapping, TempBatch, new List <object>());
             JoinsSave <ObjectType>(Object, Source, Mapping, TempBatch, new List <object>());
             TempBatch.RemoveDuplicateCommands().Execute();
         }
     }
 }
コード例 #22
0
        private void WriteList(string key, IList <string> list)
        {
            IBatch bacth = db.CreateBatch();

            if (db.KeyExists(key))
            {
                db.KeyDelete(key);
            }
            for (int i = 0; i < list.Count; i++)
            {
                bacth.ListRightPushAsync(key, list[i]);
            }
            bacth.Execute();
        }
コード例 #23
0
ファイル: UserCaching.cs プロジェクト: haositongxue/avia
        /// <summary>
        /// 锁定会员登录
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="time">要锁定的时间(分钟)</param>
        public int SaveLoginLock(int userId, int?time)
        {
            if (time == null || time.Value == 0)
            {
                return(0);
            }
            string      key   = $"{LOGIN_LOCK}{userId}";
            IBatch      batch = this.NewExecutor().CreateBatch();
            Task <long> task  = batch.StringIncrementAsync(key);

            batch.KeyExpireAsync(key, TimeSpan.FromMinutes(time.Value));
            batch.Execute();
            return((int)task.Result);
        }
コード例 #24
0
        /// <summary>
        /// 保存用户名与ID的对应关系
        /// </summary>
        /// <param name="siteId"></param>
        /// <param name="userId"></param>
        /// <param name="userName"></param>
        public void SaveUserID(int siteId, int userId, string userName)
        {
            if (siteId == 0 || userId == 0 || string.IsNullOrEmpty(userName))
            {
                return;
            }
            string hash  = userId.ToString().GetHash();
            IBatch batch = this.NewExecutor().CreateBatch();

            batch.HashSetAsync($"{USERID}{siteId}:{ userName.GetHash() }", userName, userId);
            batch.HashSetAsync($"{USERNAME}{ hash }", userId, userName);
            batch.HashSetAsync($"{USERSITE}{hash}", userId, siteId);
            batch.Execute();
        }
コード例 #25
0
        /// <summary>
        /// Returns all objects based on the parameters provided
        /// </summary>
        /// <param name="Parameters">Parameters</param>
        /// <param name="Command">Command to run</param>
        /// <param name="ConnectionString">Connection string</param>
        /// <param name="Type">Command type</param>
        /// <returns>The list of objects requested</returns>
        public static IEnumerable <dynamic> All(string Command, CommandType Type, string ConnectionString, params object[] Parameters)
        {
            var    TempParameters = Parameters as IParameter[];
            IBatch TempBatch      = Batch(ConnectionString);

            if (TempParameters == null)
            {
                TempBatch.AddCommand(null, null, Command, Type, Parameters);
            }
            else
            {
                TempBatch.AddCommand(null, null, Command, Type, TempParameters);
            }
            return(TempBatch.Execute()[0]);
        }
コード例 #26
0
        public static IEnumerable<string> GetKeys(IDatabase db)
        {
			RedisValue[] keys = db.SetMembers(ALL_KEYS));
			if (keys.Length == 0)
				return new string[0];
			List<string> expiredKeys = new List<string>(keys.Count());
			List<string> ret = new List<string>(keys.Count());
			// get expiration values using SORT with GET: https://redis.io/commands/sort
			RedisValue[] results = db.Sort(
				ALL_KEYS, 
				sortType: SortType.Alphabetic, 
				by: "notarealkey", // a (hopefully) non-existent key which causes the list to actually not be sorted
				get: new RedisValue[] { $"*{EXPIRATION_SUFFIX}", "#" } // # = "get the list item itself" which means the key in our case
			));
 
			// SORT results will be in the same order as the GET parameters: 
			// result[0] = expiration (= null if no matching expiration item found)
			// result[1] = key
			// (repeat)
			for (int i = 0; i < results.Length; i += 2)
			{
				string key = results[i + 1].Replace(EXPIRATION_SUFFIX, string.Empty);
				RedisValue expiryRedis = results[i];
				long ticks;
				if (long.TryParse(expiryRedis, out ticks))
				{
					DateTime expiry = new DateTime(ticks, DateTimeKind.Utc);
					if (expiry <= DateTime.UtcNow)
						expiredKeys.Add(key); // expired: add to list for removal
					else
						ret.Add(key);
				}
				else
					ret.Add(key);
			}
			// remove any expired keys from list
			if (expiredKeys.Count > 0)
			{
				IBatch batch = db.CreateBatch();
				batch.SetRemoveAsync(cacheKey, expiredKeys.ConvertAll(x => (RedisValue)x).ToArray());
				foreach (string expiredKey in expiredKeys)
				{
					batch.KeyDeleteAsync(expiredKey);
				}
				batch.Execute();
			}
			return ret;
       }
コード例 #27
0
 /// <summary>
 /// Deletes an object from the database
 /// </summary>
 /// <typeparam name="ObjectType">Object type</typeparam>
 /// <param name="Object">Object to delete</param>
 public void Delete <ObjectType>(ObjectType Object)
     where ObjectType : class, new()
 {
     Cache.RemoveByTag(typeof(ObjectType).GetName());
     foreach (ISourceInfo Source in SourceProvider.Where(x => x.Writable).OrderBy(x => x.Order))
     {
         IMapping Mapping = MapperProvider[typeof(ObjectType), Source];
         if (Mapping != null)
         {
             IGenerator <ObjectType> Generator = QueryProvider.Generate <ObjectType>(Source, MapperProvider[typeof(ObjectType), Source]);
             IBatch TempBatch = QueryProvider.Batch(Source);
             CascadeDelete <ObjectType>(Object, Source, Mapping, TempBatch, new List <object>());
             TempBatch.AddCommand(Generator.Delete(Object));
             TempBatch.Execute();
         }
     }
 }
コード例 #28
0
        /// <summary>
        /// 删除Token
        /// </summary>
        /// <param name="KEY">前缀KEY</param>
        /// <param name="id">要删除的ID</param>
        protected virtual void RemoveToken(string KEY, int id)
        {
            //#1 通过ID找到Token
            string     IdKey = $"{KEY}:ID";
            RedisValue token = this.NewExecutor().HashGet(IdKey, id);

            //#2 批量操作删除 ID->TOKEN  TOKEN->ID
            string tokenKey = this.GetTokenKey(KEY, id);
            IBatch batch    = this.NewExecutor().CreateBatch();

            batch.HashDeleteAsync(IdKey, id);
            if (!token.IsNull)
            {
                batch.HashDeleteAsync(tokenKey, token);
            }
            batch.Execute();
        }
コード例 #29
0
        /// <summary>
        /// Batch 批量操作
        /// </summary>
        /// <param name="action">需要执行的操作</param>
        public virtual void ExcuteWithBatch(Action <IBatch> action)
        {
            if (_database != null && action != null)
            {
                IBatch batch = _database.CreateBatch();

                try
                {
                    action(batch);

                    batch.Execute();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
コード例 #30
0
        /// <summary>
        /// This method writes the entity to the redis cache.
        /// </summary>
        /// <param name="transform">The transform holder.</param>
        /// <param name="entity">The entity to write.</param>
        /// <param name="expiry"></param>
        /// <returns>Returns true if the write was successful.</returns>
        public override async Task <bool> Write(EntityTransformHolder <K, E> transform, E entity, TimeSpan?expiry = null)
        {
            if (transform == null)
            {
                throw new ArgumentNullException(nameof(transform), "The EntityTransformHolder cannot be null.");
            }

            try
            {
                K      key     = transform.KeyMaker(entity);
                string version = transform.Version.EntityVersionAsString(entity);

                IDatabase rDb     = mLazyConnection.Value.GetDatabase();
                IBatch    batch   = rDb.CreateBatch();
                RedisKey  hashkey = RedisKeyGet(transform, key);

                var tasks = new List <Task>
                {
                    //Entity
                    batch.HashSetAsync(hashkey, cnKeyEntity, transform.CacheEntitySerializer.Serializer(entity), when: When.Always),
                    //Version
                    batch.HashSetAsync(hashkey, cnKeyVersion, version, when: When.Always),
                    // Expiry
                    batch.KeyExpireAsync(hashkey, expiry ?? mEntityTtl)
                };

                //Get any associated references for the entity.
                var references = transform.ReferenceMaker(entity);
                references?.ForEach(r => tasks.AddRange(WriteReference(batch, transform, r, key, version)));

                batch.Execute();

                await Task.WhenAll(tasks);

                return(true);
            }
            catch (Exception)
            {
                // Don't raise an exception here
            }

            return(false);
        }