async Task concurrent_providers()
        {
            const int iterations = 100000;

            var tasks = Enumerable.Range(0, iterations).Select(i =>
            {
                return(Task.Run(() =>
                {
                    var options = new RedisTempDataProviderOptions()
                    {
                        UserProvider = new FakeTempDataUserProvider("user" + i + "@example.com"),
                        Serializer = new NetDataContractTempDataSerializer()
                    };
                    var tdp = new RedisTempDataProvider(options, GetDatabase());
                    var context = new ControllerContext();
                    var tempData = tdp.LoadTempData(context);
                    tempData["id"] = 123;
                    tempData["user"] = new FakeItem()
                    {
                        Name = "User" + i
                    };
                    tdp.SaveTempData(context, tempData);

                    tempData = tdp.LoadTempData(context);
                    tempData["id"].ShouldEqual(123);
                    tempData["user"].ShouldEqual(new FakeItem()
                    {
                        Name = "User" + i
                    });
                }));
            });

            await Task.WhenAll(tasks);
        }
        async Task concurrent_providers()
        {
            const int iterations = 100000;

            var tasks = Enumerable.Range(0, iterations).Select(i =>
            {
                return Task.Run(() =>
                {
                    var options = new RedisTempDataProviderOptions()
                    {
                        UserProvider = new FakeTempDataUserProvider("user" + i + "@example.com"),
                        Serializer = new NetDataContractTempDataSerializer()
                    };
                    var tdp = new RedisTempDataProvider(options, GetDatabase());
                    var context = new ControllerContext();
                    var tempData = tdp.LoadTempData(context);
                    tempData["id"] = 123;
                    tempData["user"] = new FakeItem() { Name = "User" + i };
                    tdp.SaveTempData(context, tempData);

                    tempData = tdp.LoadTempData(context);
                    tempData["id"].ShouldEqual(123);
                    tempData["user"].ShouldEqual(new FakeItem() { Name = "User" + i });
                });
            });

            await Task.WhenAll(tasks);
        }
            void deletes_the_old_value()
            {
                var sut = new RedisTempDataProvider(options, Redis);
                Redis.Hashes[key].Add("old", "value");

                var tempData = sut.LoadTempData(context);

                Redis.Hashes[key].ShouldBeEmpty();
            }
            void deletes_the_old_value()
            {
                var sut = new RedisTempDataProvider(options, Redis);
                Redis.Set(key, "old-value");

                sut.SaveTempData(context, new Dictionary<string, object>());

                var result = Redis.Get<string>(key);
                result.ShouldBeNull();
            }
            void deletes_the_old_value()
            {
                var sut = new RedisTempDataProvider(options, Redis);
                Redis.KeyDelete(key);
                Redis.HashSet(key, "old", options.Serializer.Serialize("value"));

                var tempData = sut.LoadTempData(context);

                string result = Redis.StringGet(key);
                result.ShouldBeNull();
            }
            void deletes_the_old_value()
            {
                var sut = new RedisTempDataProvider(options, Redis);

                Redis.StringSet(key, "old-value");

                sut.SaveTempData(context, new Dictionary <string, object>());

                var result = Redis.StringGet(key);

                result.ShouldEqual(RedisValue.Null);
            }
            void deletes_the_old_value()
            {
                var sut = new RedisTempDataProvider(options, Redis);

                Redis.KeyDelete(key);
                Redis.HashSet(key, "old", options.Serializer.Serialize("value"));

                var tempData = sut.LoadTempData(context);

                string result = Redis.StringGet(key);

                result.ShouldBeNull();
            }
            void gets_each_item_deserialized()
            {
                var sut = new RedisTempDataProvider(options, Redis);
                
                sut.SaveTempData(context, new Dictionary<string, object>()
                {
                    { "A", "1" },
                    { "B", new FakeItem() { Name = "Three" } }
                });

                var tempData = sut.LoadTempData(context);

                tempData["A"].ShouldEqual("1");
                tempData["B"].ShouldEqual(new FakeItem() { Name = "Three" });
            }
            void adds_each_serialized_item_to_the_hash()
            {
                var sut = new RedisTempDataProvider(options, Redis);

                sut.SaveTempData(context, new Dictionary<string, object>()
                {
                    { "A", 1 },
                    { "B", "2" },
                    { "C", new FakeItem() { Name = "Three" } }
                });

                Redis.Hashes[key]["A"].ShouldEqual("1");
                Redis.Hashes[key]["B"].ShouldEqual("\"2\"");
                Redis.Hashes[key]["C"].ShouldEqual("{\"__type\":\"Harbour.RedisTempData.Test.FakeItem, Harbour.RedisTempData.Test\",\"Name\":\"Three\"}");
            }
            void adds_each_serialized_item_to_the_hash()
            {
                var sut = new RedisTempDataProvider(options, Redis);
                Redis.KeyDelete(key);

                sut.SaveTempData(context, new Dictionary<string, object>()
                {
                    { "A", 1 },
                    { "B", "2" },
                    { "C", new FakeItem() { Name = "Three" } }
                });

                Redis.HashGet(key, "A").ShouldEqual((RedisValue)options.Serializer.Serialize(1));
                Redis.HashGet(key, "B").ShouldEqual((RedisValue)options.Serializer.Serialize("2"));
                Redis.HashGet(key, "C").ShouldEqual((RedisValue)options.Serializer.Serialize(new FakeItem() { Name = "Three" }));
            }
            void gets_each_item_deserialized()
            {
                var sut = new RedisTempDataProvider(options, Redis);

                Redis.KeyDelete(key);

                sut.SaveTempData(context, new Dictionary <string, object>()
                {
                    { "A", "1" },
                    { "B", new FakeItem()
                      {
                          Name = "Three"
                      } }
                });

                var tempData = sut.LoadTempData(context);

                tempData["A"].ShouldEqual("1");
                tempData["B"].ShouldEqual(new FakeItem()
                {
                    Name = "Three"
                });
            }
            void adds_each_serialized_item_to_the_hash()
            {
                var sut = new RedisTempDataProvider(options, Redis);

                Redis.KeyDelete(key);

                sut.SaveTempData(context, new Dictionary <string, object>()
                {
                    { "A", 1 },
                    { "B", "2" },
                    { "C", new FakeItem()
                      {
                          Name = "Three"
                      } }
                });

                Redis.HashGet(key, "A").ShouldEqual((RedisValue)options.Serializer.Serialize(1));
                Redis.HashGet(key, "B").ShouldEqual((RedisValue)options.Serializer.Serialize("2"));
                Redis.HashGet(key, "C").ShouldEqual((RedisValue)options.Serializer.Serialize(new FakeItem()
                {
                    Name = "Three"
                }));
            }