SỬ DỤNG RAVENDB – NOSQL TRONG ASP.NET MVC

Bài trước tôi đã giới thiệu các khái niệm về NoSql, bài này tôi xin được trình bày việc sử dụng NoSql trong một Asp.net MVC đơn giản. RavenDB cũng là open source được viết bằng C# nên thông qua nó ta có thể tìm hiểu được cơ chế của NoSql một cách thuận tiện hơn.

1. Các bước setup cơ bản ban đầu.

  • Bắt đầu với việc tạo project Asp.net MVC

Chọn template là internet project.

  • Add RavenDB (Embedded) reference bằng cách Tool > Extension and Update search online RavenDB.

2. Chỉnh sửa Model và Controller.

  • Add project class library, chứa các class model, ở đây ta lấy ví dụ là database của một blog chứa nhiều comment.

  • Trong project này, ta tạo thư mục model và add 2 class Blog.cs và Comment.cs

RavenDB sẽ lưu trữ data thông qua DocumentStore object. Ta cần implement IDocumentStore interface. Mọi ‘connection’ đến DocumentStore được thông qua RavenDB DocumentSession. Để sử dụng tầng RavenDB access layer ta làm theo các bước sau:

  • Tạo RavenController class được kế thừa từ MVC’s Controller class, class này được đặt trong thư mục Controller.
public class RavenController : Controller
{
public new IDocumentSession Session { get; set; }

protected IDocumentStore _documentStore;

public RavenController(IDocumentStore documentStore)
{
_documentStore = documentStore;
}

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
Session = _documentStore.OpenSession();
base.OnActionExecuting(filterContext);
}

protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
using (Session)
{
if(Session!=null && filterContext.Exception == null)
{
Session.SaveChanges();
}
}
base.OnActionExecuted(filterContext);
}
}
  • Chúng ta đã chuẩn bị xong base controller, giờ ta sẽ chuyển qua HomeContoller và thay đổi để nó kế thừa từ RavenController thay cho controller default của MVC.
public class HomeController : RavenController
{
public HomeController(IDocumentStore store)
: base(store)
{

}
  • Chúng ta load một một row data của Blog từ RavenDB bằng cách như sau.

//
// GET: /Home/Details/5

public ViewResult Details(int id)
{
Blog blog = Session.Load<Blog>(id);
return View(blog);
}

- Danh sách các Blog được load như sau:

public ActionResult Index()
{
return View(Session.Query<Blog>().ToList());
}

  • Update Blog và save vào RavenDB
//
// POST: /Home/Edit/5

[HttpPost]
public ActionResult Edit(Blog blog)
{
if (ModelState.IsValid)
{
Blog currentBlog = Session.Load<Blog>(blog.Id);
currentBlog.Title = blog.Title;
currentBlog.Content = blog.Content;
Session.Store(currentBlog);
return RedirectToAction(“Index”);
}
return View(blog);
}

RavenDB’s document session sẽ không updates ngay vào document. Khi chúng ta trực tiếp chỉnh sửa blog object thì sự thay đổi sẽ được lưu vào session store. Trong các bước tiếp theo chúng ta sẽ đề cập đến vấn đề này sau.

  • Các action khác được định nghĩa các bạn có thể xem thêm trong source code để biết chi tiết thêm.

2. Implement cho View.

Phần tiếp theo ta implement view để hiển thị các chức năng danh sách blog, view detail block …

  • Chúng ta sửa file Details.cshtml để hiển thị các comment của user.
</div>
<div class=”blog-item-footer”>
@Html.ActionLink(“Edit”, “Edit”, new { id = Model.Id }) |
@Html.ActionLink(Back to List”, “Index”)
</div>
<div class=”blog-item-content”>
@Html.DisplayFor(model => model.Content)
</div>
<div>
@if (Model.Comments != null)
{
<div>
<h3>User Feedback</h3>
</div>
foreach (var item in Model.Comments)
{
<div style=”border: solid 1px #F0F0F0; margin: 2px”>
<div class=”comment-author”>
Comments by – @item.Author
</div>
<div class=”comment-message”>
@item.Message
</div>
</div>
}
}
</div>
<div id=”addComments” style=”display: inline;>
<div>
@Html.Partial(“CreateComments”, new RaBlog.Domain.Model.Comment { BlogId = Model.Id })
</div>
</div>
  • Bước kế tiếp ta add thêm 1 file Partial View đặt tên là CreateComments.cshtml.
@model RaBlog.Domain.Model.Comment
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>Post Comment</legend>
@Html.HiddenFor(model => model.BlogId)
<div style=”height:35px;>
<div class=”editor-label” style=float:left; width:125px”>
@Html.LabelFor(model => model.Author)
</div>
<div class=”editor-field” style=float:left;>
@Html.EditorFor(model => model.Author)
@Html.ValidationMessageFor(model => model.Author)
</div>
</div>
<div style=”height:35px;>
<div class=”editor-label” style=float:left; width:125px”>
@Html.LabelFor(model => model.Email)
</div>
<div class=”editor-field” style=float:left”>
@Html.EditorFor(model => model.Email)
@Html.ValidationMessageFor(model => model.Email)
</div>
</div>
<div style=”height:35px;>
<div class=”editor-label” style=float:left; width:125px”>
@Html.LabelFor(model => model.Message)
</div>
<div class=”editor-field” style=float:left;>
@Html.TextAreaFor(model => model.Message, new { rows = 5, cols = 100 })
@Html.ValidationMessageFor(model => model.Message)
</div>
</div>
<p>
<input type=”submit” name=”CreateComment” value=Post Comment” />
</p>
</fieldset>
  • Ở file Controller chúng ta cần handle action POST từ CreateComments view.
//
// POST: /Home/Details
[HttpPost]
public ActionResult Details(Comment comment)
{
Blog blog = Session.Load<Blog>(comment.BlogId);
if (blog.Comments == null)
{
blog.Comments = new List<Comment>();
}
blog.Comments.Add(comment);

Session.Store(blog);
return RedirectToAction(“Details”, comment.BlogId);
}

3. Control DocumentStore .

  • Chúng ta cần cơ chế để khởi tạo, kết nối với DocumentStore của RavenDB.

  • Ta implement việc kết nối đến DocumentStore thông qua method CreateControllerFactory trong class CompositionRoot

public class CompositionRoot
{
private readonly IControllerFactory controllerFactory;

public CompositionRoot()
{
this.controllerFactory = CompositionRoot.CreateControllerFactory();
}

public IControllerFactory ControllerFactory
{
get
{
return controllerFactory;
}
}

private static IControllerFactory CreateControllerFactory()
{
var cacheRepository = new EmbeddableDocumentStore();
cacheRepository.ConnectionStringName = “RavenDB”;
cacheRepository.Initialize();
var controllerFactory = new BlogControllerFactory(cacheRepository);
return controllerFactory;
}

}
  • Như ở trên để khởi tạo instance của EmbeddableDocumentStore() chúng ta cần cung cấp ConnectionStringName – tên DB. connection string sẽ được định nghĩa trong web.config.

raven-db-embedded-connection-string

Sau các bước trên, giờ bạn chỉ còn 1 bước cuối là ấn F5 và chạy thử 😄

link source code:

https://onedrive.live.com/redir?resid=AAAFFCDAE249948A!116&authkey=!AHPcc6UbwfZLEvQ&ithint=file%2Czip