C# 에서 Redis 에 데이터를 저장하고 가져오기 위해서 찾아본 라이브러리 중에서 "CloudStructers" 가 있었다. 간편한 사용법에 클래스를 serialze/desirialize 할 수있고, async 가 지원된다는 장점이 있다. 그외 Rx 도 같이 되는거 같은데, 깃허브에 관련 내용이 있다.
클래스를 Redis Hash 구조체로 만들어주는 RedisClass<> 가 있어서 프로젝트에 이용하려고 테스트 예제를 짜는데, 원 클래스를 상속받은 자식클래스 인스턴스를 선언하고 (부모클래스에 있는 모든)멤버 변수에다가 값을 저장후 Redis 에 저장해보니 제대로 동작을 안한다.
- 소스
public class Person { public string Name { get; set; } public int Age { get; set; } } public class Child : Person { public int Sex { get; set; } public string LastName { get; set; } } [TestClass] public class UnitTest2 { public static readonly RedisSettings redisSetting = new RedisSettings("IP"); [TestMethod] public void TestMethod1() { var redisObj = new RedisString(redisSetting, "idid"); Child child = new Child(); child.Name = "Alice"; child.Age = 18; child.Sex = 1; redisObj.Set(child); } }
Person 클래스를 상속받은 Child 클래스 인스턴스를 생성하고 값을 저장하고 Redis 로 Set 를 했는데, 실제 Redis 서버에 저장된 내용은 Child 의 멤버 변수만 저장이 된다.
127.0.0.1:6379> get idid
"\xef\xbb\xbf{\"Sex\":1,\"LastName\":null}"
원인을 분석해보려고 깃허브에 올라온 소스를 확인해보니깐, ValueConverter.Serialize() 에서 문제가 되는듯해서, ValueConverter 를 보니, JSON serialize 라이브러인 Jil 을 사용하는 부분에서 subclass 까지 Serialzie 하는 SerializeDynamic() 을 이용안해서 이런 문제가 발생한듯했다.(https://github.com/kevin-montrose/Jil#dynamic-serialization)
- RedisString.cs
////// SET http://redis.io/commands/set /// public TaskSet(T value, RedisExpiry expiry = null, When when = When.Always, CommandFlags commandFlags = CommandFlags.None) { return TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async () => { long sentSize; var v = Settings.ValueConverter.Serialize(value, out sentSize); bool r; if (expiry != null && expiry.IsTimeSpan) { r = await Command.StringSetAsync(Key, v, (TimeSpan)expiry.Value, when, CommandFlags.None).ForAwait(); } else { r = await this.ExecuteWithKeyExpire(x => x.StringSetAsync(Key, v, expiry: null, when: when, flags: commandFlags), Key, expiry, commandFlags).ForAwait(); } return Tracing.CreateSentAndReceived(new { value, expiry, when }, sentSize, r, sizeof(bool)); }); }
소스를 받아서 수정해야하나 고민하다가, 다른 라이브러리를 찾아보다가 "CloudStructers" 가 이용하는 "StackeExchange.Redis" 를 알아보았다. StackExchange 도 pipeline 기능도 지원해서(async 도 지원), 간단 예제를 작성해보니 쉽게 사용할 수 있었을 거 같았다. Redis 의 여러 자료구조들은 다 지원을 하는데, 클래스 단위로 저장할 수 있는 방법은 없은거 같아서 다시 찾아보니, "StackExchange.Redis.Extension" 이 있었다.
- 테스트 유닛 소스
public class Person2 { public string Name { get; set; } public int Age { get; set; } } public class Child2 : Person2 { public int Sex { get; set; } public string LastName { get; set; } } [TestClass] public class UnitTestStackExchange { [TestMethod] public void TestMethod1() { ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("IP"); IDatabase db = redis.GetDatabase(0, null); db.StringSet("mykey", "abcdef"); string value = db.StringGet("mykey"); Console.WriteLine("Value:" + value); } [TestMethod] public void TestMethod2() { var serializer = new NewtonsoftSerializer(); var cacheClient = new StackExchangeRedisCacheClient(serializer); Child2 child = new Child2(); child.Name = "Alice"; child.Age = 18; child.Sex = 1; cacheClient.Add("my-key", child); }
- App.config : StackExchangeRedisCacheClient() 파라미터로 넘기는 serializer 를 App.config 를 통해서 설정하고 컨테이너에 등록해야한다.
참조 사이트 :
- CloudStructures.Redis
https://github.com/neuecc/CloudStructures
- Jil
https://github.com/kevin-montrose/Jil
- StackExchane.Redis 사용 예제 블로그
http://tostring.it/2015/04/23/An-easy-way-to-use-StackExchange-Redis%20copy/
- StackExchange.Redis.Extension
https://github.com/imperugo/StackExchange.Redis.Extensions
'Engineering > C#' 카테고리의 다른 글
excel2json 자바스크립트 (0) | 2015.08.12 |
---|---|
DateTime 값으로 Tick 값을 구하는 C# 코드 (0) | 2013.11.13 |