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 |