ºÜ¾ÃÒÔǰдÁËһƪÎÄÕ .NETÖÐʹÓÃRedis ½éÉÜÁËÈçºÎ°²×°Redis·þÎñ¶Ë£¬ÒÔ¼°ÈçºÎÔÚ.NETÖе÷ÓÃRedis¶ÁÈ¡Êý¾Ý¡£±¾Îļòµ¥½éÉÜÈçºÎÉè¼ÆNoSQLÊý¾Ý¿â£¬ÒÔ¼°ÈçºÎʹÓÃRedisÀ´´æ´¢¶ÔÏó¡£
ºÍ´«Í³µÄ¹ØÏµÐÍÊý¾Ý¿â²»Í¬£¬NoSQL´ó²¿·Ö¶¼ÊÇÒÔ¼üÖµ¶Ô´æ´¢ÔÚÄÚ´æÖеģ¬ÎÒÃDz»ÄÜÖ±½Ó°ÑRDBMSÀïÃæµÄһЩ×ö·¨Ö±½ÓÒÆÖ²µ½NoSQLÖÐÀ´£¬Ò»¸ö×îÖ÷ÒªµÄÔÒòÊÇ£¬ÔÚNoSQLÖÐȱÉÙRDBMSÖеÄһЩÖîÈçjoin
,unionÒÔ¼°Ò»Ð©ÔÚ¹ØÏµÐÍÊý¾Ý¿âÖÐЧÂʺܸߵÄÖ´ÐÐÓï¾ä£¬ÕâЩÔÚNoSQL²»ÄܺܺõÄÖ§³Ö£¬»òÕß˵ЧÂʵ͡£
ÏÂÎÄÊ×ÏÈͨ¹ýÀý×Ó½éÉÜÔÚSQLServerÖÐÉè¼ÆÒ»¸öDBϵͳÒÔ¼°ÓëNoSQL»·¾³ÖÐÉè¼ÆÒ»¸öDBµÄÇø±ð£¬×îºóÑÝʾÈçºÎÔÚRedisÖжÔÊý¾Ý½øÐжÁд²Ù×÷¡£
Ò»¸ö¼òµ¥µÄ²©¿Íϵͳ
¼ÙÉèÎÒÃÇÒªÉè¼ÆÒ»¸ö¼òµ¥µÄ²©¿Íϵͳ£¬Óû§¿ÉÒÔ×¢²áÒ»¸ö²©¿Í(Blog)£¬È»ºó¿ÉÒÔÔÚÉÏÃæÐ´ÎÄÕÂ(Post)£¬ÎÄÕ¿ÉÒÔ·ÖÀà(Category)ÒÔ¼°Ìí¼Ó±êÇ©(Tag)£¬Óû§¿ÉÒÔ¶ÔÎÄÕ½øÐÐÆÀÂÛ(Comment)¡£
ÔÚ¸ÃϵͳÖУ¬ÎÒÃÇÐèҪʵÏÖ£¬ÈçÏ»ù±¾¹¦ÄÜ£º
1.Ê×Ò³£ºÏÔʾËùÓÐÈ˵IJ©¿Í
2.Ê×Ò³£ºÏÔʾ×î½üµÄËùÓз¢±íµÄÎÄÕÂ
3.Ê×Ò³£ºÏÔʾËùÓеÄ×î½üµÄÆÀÂÛ
4.Ê×Ò³£ºÏÔʾ²©¿ÍµÄ±êÇ©ÔÆ
5.Ê×Ò³£ºÏÔʾËùÓеķÖÀà
6.ÎÄÕÂÒ³Ãæ£ºÏÔʾÎÄÕÂÒÔ¼°ËùÓÐµÄÆÀÂÛ
7.ÎÄÕÂÒ³Ãæ£ºÌí¼ÓÆÀÂÛ
8.±êÇ©Ò³Ãæ£ºÏÔʾËùÓбêÇ©ÒÔ¼°±êÇ©¶ÔÓ¦µÄÎÄÕÂ
9.·ÖÀàÒ³Ãæ£ºÏÔʾËùÓзÖÀàÒÔ¼°·ÖÀà¶ÔÓ¦µÄÎÄÕÂ
Èç¹ûÔÚSQLServerÖУ¬ÏàÐźܼòµ¥¾Í¿ÉÒÔÉè¼Æ³öÕâÑùÒ»¸öDBÁË¡£

ÔÚNoSQL»·¾³ÖУ¬ÎÒÃDz»ÄÜÖ±½Ó½«ÉÏÃæµÄ½á¹¹°á½øÀ´£¬ËùÒÔÐèÒª¸ù¾ÝÐèÇóÖØÐÂÉè¼ÆÎÒÃǵÄÄ£ÐÍ¡£
¶¨ÒåʵÌå
ÔÚNoSQL»·¾³Ï£¬ËùÓеÄÊý¾ÝÆäʵ¶¼ÊÇÒÔkeyºÍvalueµÄÐÎʽ´æ´¢ÔÚÄÚ´æÖеģ¬valueͨ³£ÊÇÐòÁл¯Îª×Ö·û´®±£´æµÄ¡£ÎÒÃÇʹÓÃredis¿Í»§¶ËµÄʱºò£¬¿ÉÒÔÖ±½Ó½«¶ÔÏó´æ´¢£¬ÕâЩ¿Í»§¶ËÔÚÄÚ²¿ÊµÏÖÉϰïÖúÎÒÃǽøÐÐÁËÐòÁл¯¡£ËùÒÔµÚÒ»²½¾ÍÊÇÐèÒª¶¨ÒåʵÌåÄ£ÐÍ£º
Ê×ÏÈÀ´¿´UserʵÌ壺
public class User
{
public User()
{
this.BlogIds = new List();
}
public long Id { get; set; }
public string Name { get; set; }
public List BlogIds { get; set; }
} |
UserʵÌåÖУ¬°üº¬ÁËÓû§µÄId£¬NameÒÔ¼°²©¿ÍµÄId¡£
È»ºóBlogʵÌå:
public class Blog
{
public Blog()
{
this.Tags = new List();
this.BlogPostIds = new List();
}
public long Id { get; set; }
public long UserId { get; set; }
public string UserName { get; set; }
public List Tags { get; set; }
public List BlogPostIds { get; set; }
} |
°üº¬Á˱êÇ©Tag£¬ÒÔ¼°ÎÄÕÂIdÁÐ±í¡£
ÎÄÕÂBolgPostʵÌ壺
public class BlogPost
{
public BlogPost()
{
this.Categories = new List();
this.Tags = new List();
this.Comments = new List();
}
public long Id { get; set; }
public long BlogId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public List Categories { get; set; }
public List Tags { get; set; }
public List Comments { get; set; }
} |
°üº¬ÁËһƪÎÄÕµĻù±¾ÐÅÏ¢£¬ÈçÎÄÕ·ÖÀ࣬ÎÄÕ±êÇ©£¬ÎÄÕÂµÄÆÀÂÛ¡£
×îºó¿´ÆÀÂÛBlogPostCommentʵÌ壺
public class BlogPostComment
{
public string Content { get; set; }
public DateTime CreatedDate { get; set; }
} |

¾ßÌåʵÏÖ
ʵÌ嶨ÒåºÃÁËÖ®ºó£¬ÎÒÃǾͿÉÒÔ¿ªÊ¼¾ßÌåʵÏÖÁË¡£ÎªÁËÑÝʾ£¬ÕâÀïͨ¹ýµ¥Ôª²âÊԵķ½Ê½ÊµÏÖ¾ßÌ幦ÄÜ£º
Ê×ÏÈÒª°ÑRedisµÄ·þÎñ¶ËÆô¶¯ÆðÀ´£¬È»ºóÔÚ¹¤³ÌÖÐн¨Ò»¸öRedis¿Í»§¶Ë£¬Ö®ºóµÄËùÓвÙ×÷¶¼Í¨¹ýÕâ¸ö¿Í»§¶Ë½øÐС£
[TestFixture, Explicit, Category("Integration")]
public class BlogPostExample
{
readonly RedisClient redis = new RedisClient("localhost");
[SetUp]
public void OnBeforeEachTest()
{
redis.FlushAll();
InsertTestData();
}
} |
ÔÚµ¥Ôª²âÊÔµÄSetUpÖУ¬ÎÒÃDzåÈëһЩģÄâÊý¾Ý£¬²åÈëÊý¾ÝµÄ·½·¨ÎªInsetTestData·½·¨£º
public void InsertTestData()
{
var redisUsers = redis.As();
var redisBlogs = redis.As();
var redisBlogPosts = redis.As();
var yangUser = new User { Id = redisUsers.GetNextSequence(), Name = "Eric Yang" };
var zhangUser = new User { Id = redisUsers.GetNextSequence(), Name = "Fish Zhang" };
var yangBlog = new Blog
{
Id = redisBlogs.GetNextSequence(),
UserId = yangUser.Id,
UserName = yangUser.Name,
Tags = new List { "Architecture", ".NET", "Databases" },
};
var zhangBlog = new Blog
{
Id = redisBlogs.GetNextSequence(),
UserId = zhangUser.Id,
UserName = zhangUser.Name,
Tags = new List { "Architecture", ".NET", "Databases" },
};
var blogPosts = new List
{
new BlogPost
{
Id = redisBlogPosts.GetNextSequence(),
BlogId = yangBlog.Id,
Title = "Memcache",
Categories = new List { "NoSQL", "DocumentDB" },
Tags = new List {"Memcache", "NoSQL", "JSON", ".NET"} ,
Comments = new List
{
new BlogPostComment { Content = "First Comment!", CreatedDate = DateTime.UtcNow,},
new BlogPostComment { Content = "Second Comment!", CreatedDate = DateTime.UtcNow,},
}
},
new BlogPost
{
Id = redisBlogPosts.GetNextSequence(),
BlogId = zhangBlog.Id,
Title = "Redis",
Categories = new List { "NoSQL", "Cache" },
Tags = new List {"Redis", "NoSQL", "Scalability", "Performance"},
Comments = new List
{
new BlogPostComment { Content = "First Comment!", CreatedDate = DateTime.UtcNow,}
}
},
new BlogPost
{
Id = redisBlogPosts.GetNextSequence(),
BlogId = yangBlog.Id,
Title = "Cassandra",
Categories = new List { "NoSQL", "Cluster" },
Tags = new List {"Cassandra", "NoSQL", "Scalability", "Hashing"},
Comments = new List
{
new BlogPostComment { Content = "First Comment!", CreatedDate = DateTime.UtcNow,}
}
},
new BlogPost
{
Id = redisBlogPosts.GetNextSequence(),
BlogId = zhangBlog.Id,
Title = "Couch Db",
Categories = new List { "NoSQL", "DocumentDB" },
Tags = new List {"CouchDb", "NoSQL", "JSON"},
Comments = new List
{
new BlogPostComment {Content = "First Comment!", CreatedDate = DateTime.UtcNow,}
}
},
};
yangUser.BlogIds.Add(yangBlog.Id);
yangBlog.BlogPostIds.AddRange(blogPosts.Where(x => x.BlogId == yangBlog.Id).Map(x => x.Id));
zhangUser.BlogIds.Add(zhangBlog.Id);
zhangBlog.BlogPostIds.AddRange(blogPosts.Where(x => x.BlogId == zhangBlog.Id).Map(x => x.Id));
redisUsers.Store(yangUser);
redisUsers.Store(zhangUser);
redisBlogs.StoreAll(new[] { yangBlog, zhangBlog });
redisBlogPosts.StoreAll(blogPosts);
} |
ÔÚ·½·¨ÖУ¬Ê×ÏÈÔÚRedisÖд´½¨ÁËÈý¸öÇ¿ÀàÐ͵ÄIRedisTypedClientÀàÐ͵ĶÔÏóredisUsers,redisBlogs,redisBlogPostsÀ´±£´æÓû§ÐÅÏ¢£¬²©¿ÍÐÅÏ¢£¬ºÍÎÄ×ÖÐÅÏ¢¡£
var yangUser = new User { Id = redisUsers.GetNextSequence(), Name = "Eric Yang" }; |
ÔÚн¨Óû§µÄʱºò£¬ÒòΪIdÊÇ×ÔÔö×ֶΣ¬ËùÒÔÖ±½Óµ÷ÓÃredisUsersÕâ¸öclientµÄGetNextSequence()·½·¨¾Í¿ÉÒÔ»ñµÃÒ»¸ö×ÔÔöµÄId¡£
´´½¨ÍêÓû§Ö®ºó£¬½Ó×Å´´½¨²©¿ÍÐÅÏ¢:
var yangBlog = new Blog { Id = redisBlogs.GetNextSequence(), UserId = yangUser.Id, UserName = yangUser.Name, Tags = new List<string> { "Architecture", ".NET", "Databases" }, }; |
¸Ã²©¿ÍÓм¸¸ö±êÇ©¡£
ÔÚ½Ó×Å´´½¨¸Ã²©¿ÍÉÏ·¢±íµÄÈô¸ÉƪÎÄÕ£º
var blogPosts = new List<BlogPost> { new BlogPost { Id = redisBlogPosts.GetNextSequence(), BlogId = yangBlog.Id, Title = "Memcache", Categories = new List<string> { "NoSQL", "DocumentDB" }, Tags = new List<string> {"Memcache", "NoSQL", "JSON", ".NET"} , Comments = new List<BlogPostComment> { new BlogPostComment { Content = "First Comment!", CreatedDate = DateTime.UtcNow,}, new BlogPostComment { Content = "Second Comment!", CreatedDate = DateTime.UtcNow,}, } } } |
ÿһƪÎÄÕ¶¼ÓзÖÀàºÍ±êÇ©£¬ÒÔ¼°ÆÀÂÛ¡£
È»ºóÐèÒª¸øuserµÄBlogsIdsºÍblogµÄBlogPostIds¸³Öµ
yangUser.BlogIds.Add(yangBlog.Id); yangBlog.BlogPostIds.AddRange(blogPosts.Where(x => x.BlogId == yangBlog.Id).Map(x => x.Id)); |
×îºóÐèÒª°ÑÕâЩÐÅÏ¢±£´æµ½redisÖС£
//±£´æÓû§ÐÅÏ¢ redisUsers.Store(yangUser); redisUsers.Store(zhangUser); //±£´æ²©¿ÍÐÅÏ¢ redisBlogs.StoreAll(new[] { yangBlog, zhangBlog }); //±£´æËùÓеÄÎÄÕÂÐÅÏ¢ redisBlogPosts.StoreAll(blogPosts); |
ÏÖÔÚ£¬ÀûÓÃRedis Desktop Manager£¬¿ÉÒԲ鿴ReidisÖд洢µÄÊý¾Ý£º

Êý¾Ý×¼±¸ºÃÁËÖ®ºó£¬¿ÉÒÔʵÏÖÇ°ÃæÁгöµÄһϵÁз½·¨ÁË£º
ÏÔʾËùÓв©¿Í
¸Ã·½·¨ÔÚGetAllBlogsÖУ¬ÊµÏÖÈçÏ£º
[Test] public void Show_a_list_of_blogs() { var redisBlogs = redis.As<Blog>(); var blogs = redisBlogs.GetAll(); blogs.PrintDump(); } |
Ö»ÐèÒªµ÷ÓÃGetAll·½·¨¼´¿É»ñÈ¡ÄÚ´æÖеÄËùÓÐÖ¸¶¨ÀàÐ͵ĶÔÏó¡£
Êä³ö½á¹ûΪ£º
[ { Id: 1, UserId: 1, UserName: Eric Yang, Tags: [ Architecture, .NET, Databases ], BlogPostIds: [ 1, 3 ] }, { Id: 2, UserId: 2, UserName: Fish Zhang, Tags: [ Architecture, .NET, Databases ], BlogPostIds: [ 2, 4 ] } ] |
ÏÔʾ×î½ü·¢±íµÄÎÄÕÂºÍÆÀÂÛ
ʵÏÖÈçÏÂ:
[Test]
public void Show_a_list_of_recent_posts_and_comments()
{
//Get strongly-typed clients
var redisBlogPosts = redis.As();
var redisComments = redis.As();
{
//To keep this example let's pretend this is a new list of blog posts
var newIncomingBlogPosts = redisBlogPosts.GetAll();
//Let's get back an IList wrapper around a Redis server-side List.
var recentPosts = redisBlogPosts.Lists["urn:BlogPost:RecentPosts"];
var recentComments = redisComments.Lists["urn:BlogPostComment:RecentComments"];
foreach (var newBlogPost in newIncomingBlogPosts)
{
//Prepend the new blog posts to the start of the 'RecentPosts' list
recentPosts.Prepend(newBlogPost);
//Prepend all the new blog post comments to the start of the 'RecentComments' list
newBlogPost.Comments.ForEach(recentComments.Prepend);
}
//Make this a Rolling list by only keep the latest 3 posts and comments
recentPosts.Trim(0, 2);
recentComments.Trim(0, 2);
//Print out the last 3 posts:
recentPosts.GetAll().PrintDump();
recentComments.GetAll().PrintDump();
}
} |
·½·¨Öж¨ÒåÁËÁ½¸ökeyΪurn:BlogPost:RecentPosts ºÍ urn:BlogPostComment:RecentCommentsµÄ
List¶ÔÏóÀ´±£´æ×î½ü·¢±íµÄÎÄÕÂºÍÆÀÂÛ£ºrecentPosts.Prepend(newBlogPost)·½·¨±íʾ½«Ð´´½¨µÄÎÄÕ²嵽recentPostsÁбíµÄ×îÇ°Ãæ¡£
Trim·½·¨±íʾ½ö±£Áôn¸öÔÚ¼¯ºÏÖС£
ÏÔʾ²©¿ÍµÄ±êÇ©ÔÆ
ÏÔʾ²©¿ÍµÄ±êÇ©ÔÆ·½·¨ÈçÏ£º
[Test]
public void Show_a_TagCloud()
{
//Get strongly-typed clients
var redisBlogPosts = redis.As();
var newIncomingBlogPosts = redisBlogPosts.GetAll();
foreach (var newBlogPost in newIncomingBlogPosts)
{
//For every tag in each new blog post, increment the number of times each Tag has occurred
newBlogPost.Tags.ForEach(x =>
redis.IncrementItemInSortedSet("urn:TagCloud", x, 1));
}
//Show top 5 most popular tags with their scores
var tagCloud = redis.GetRangeWithScoresFromSortedSetDesc("urn:TagCloud", 0, 4);
tagCloud.PrintDump();
} |
ÏÔʾ±êÇ©ÔÆµÄʵÏÖ£¬Óõ½ÁËredisÖеÄSortedSet£¬IncrementItemInSortedSet±íʾÈç¹ûÓÐÏàͬµÄ»°£¬Öµ¼ÓÒ»£¬GetRangeWithScoresFromSortedSetDesc·½·¨£¬»ñȡijһkeyµÄǰ5¸ö¶ÔÏó¡£
ÏÔʾËùÓеķÖÀà
ÏÔʾËùÓеķÖÀàÓõ½ÁËSet¶ÔÏó¡£
[Test]
public void Show_all_Categories()
{
var redisBlogPosts = redis.As();
var blogPosts = redisBlogPosts.GetAll();
foreach (var blogPost in blogPosts)
{
blogPost.Categories.ForEach(x =>
redis.AddItemToSet("urn:Categories", x));
}
var uniqueCategories = redis.GetAllItemsFromSet("urn:Categories");
uniqueCategories.PrintDump();
} |
ÏÔʾÎÄÕÂÒÔ¼°ÆäÆÀÂÛ
ʵÏÖÈçÏÂ:
[Test]
public void Show_post_and_all_comments()
{
//There is nothing special required here as since comments are Key Value Objects
//they are stored and retrieved with the post
var postId = 1;
var redisBlogPosts = redis.As();
var selectedBlogPost = redisBlogPosts.GetById(postId.ToString());
selectedBlogPost.PrintDump();
} |
Ö»ÐèÒª°ÑpostId´«½øÈ¥¾Í¿ÉÒÔͨ¹ýGetByIdµÄ·½·¨»ñÈ¡ÄÚ´æÖеĶÔÏó.
Ìí¼ÓÆÀÂÛ
Ê×Ïȸù¾ÝPostId»ñÈ¡BlogPost£¬È»ºóÔÚCommentÊôÐÔÖÐÌí¼ÓÒ»¸öBlogPostComment¶ÔÏó£¬È»ºóÔÚ±£´æ¸ÄBlogPost.
[Test]
public void Add_comment_to_existing_post()
{
var postId = 1;
var redisBlogPosts = redis.As();
var blogPost = redisBlogPosts.GetById(postId.ToString());
blogPost.Comments.Add(
new BlogPostComment { Content = "Third Post!", CreatedDate = DateTime.UtcNow });
redisBlogPosts.Store(blogPost);
var refreshBlogPost = redisBlogPosts.GetById(postId.ToString());
refreshBlogPost.PrintDump();
} |
ÏÔʾ·ÖÀàÒÔ¼°·ÖÀà¶ÔÓ¦µÄÎÄÕÂ
[Test]
public void Show_all_Posts_for_the_DocumentDB_Category()
{
var redisBlogPosts = redis.As();
var newIncomingBlogPosts = redisBlogPosts.GetAll();
foreach (var newBlogPost in newIncomingBlogPosts)
{
//For each post add it's Id into each of it's 'Cateogry > Posts' index
newBlogPost.Categories.ForEach(x =>
redis.AddItemToSet("urn:Category:" + x, newBlogPost.Id.ToString()));
}
//Retrieve all the post ids for the category you want to view
var documentDbPostIds = redis.GetAllItemsFromSet("urn:Category:DocumentDB");
//Make a batch call to retrieve all the posts containing the matching ids
//(i.e. the DocumentDB Category posts)
var documentDbPosts = redisBlogPosts.GetByIds(documentDbPostIds);
documentDbPosts.PrintDump();
} |
ÕâÀïÊ×ÏȰÑËùÓеÄÎÄÕ°´ÕÕ±êǩн¨Set£¬°ÑÏàͬµÄ·ÖÀàµÄÎÄÕ·ŵ½Ò»¸öSetÖУ¬×îºó¸ù¾Ýkey¼´¿É²éÕÒµ½ÏàÓ¦µÄ¼¯ºÏ¡£
×ܽá
±¾ÎÄÀûÓÃÒ»¸ö¼òµ¥µÄ²©¿Íϵͳ£¬¼òÒª½éÉÜÁËÈçºÎÀûÓÃRedis´æ´¢ºÍ»ñÈ¡¸´ÔÓµÄÊý¾Ý¡£ÓÉÓÚ±¾ÎÄÖ÷ҪΪÁËÑÝʾÈçºÎÓëRedis½øÐн»»¥£¬ËùÒÔʵÌåÉè¼ÆµÄºÜ¼òª£¬Ã»Óа´ÕÕDDDµÄ˼Ïë½øÐÐÉè¼Æ£¬ÔÚijЩÉè¼Æ·½ÃæÃ»ÓÐ×ñÑǰÎÄdz̸ÒÀÀµ×¢ÈëÖÐʹÓõÄÔÀíºÍ·½·¨£¬ºóÃæ»áдÎÄÕ¶ԸÃϵͳ½øÐÐÖØ¹¹ÒÔʹ֮¸ü¼ÓÍêÉÆ¡£
Ï£Íû±¾ÎĶÔÄúÁ˽âÈçºÎÀûÓÃRedis´æ´¢¸´ÔÓ¶ÔÏóÓÐËù°ïÖú¡£
|