Доска рекордов на WCF и RavenDB. Хранение данных

16.04.2014 at 19:32

В предыдущей части мы сделали сервис. Теперь напишем для него прокси, который будет использоваться в клиентском коде. Прокси для WCF сервисов можно генерировать прямо в студии: в контекстном меню на узле Refernces -> Add Service Reference, далее указываем адрес сервиса, нажимаем Go — и получаем сгенерированный прокси класс.


Можно оставить сгенерированный класс без изменений, но я решил удалить все лишнее.

/// <summary>
/// Клиент для доски рекордов.
/// </summary>
public class ScoreBoardClient : ClientBase<IScoreBoard>, IScoreBoard
{
  public ScoreBoardClient(string remoteAddress) :
    base(new NetTcpBinding(), new EndpointAddress(remoteAddress)) { }

  public List<ScoreBoardResult> GetTopResults(int count)
  {
    return base.Channel.GetTopResults(count);
  }
    
  public void AddResult(ScoreBoardResult result)
  {
    base.Channel.AddResult(result);
  }
}

Конструктор я добавил для большего удобства использования.

Хранение данных

Для хранения данных буду использовать RavenDB. Никаких особых причин для этого нет, просто давно хотелось попробовать. Идем на сайт ravendb.net и скачиваем последнюю версию в архиве. Распаковываем архив и добавляем в проект всю папку EmbeddedClient.
Создаем хранилище

this.documentStore = new EmbeddableDocumentStore 
{ 
  DataDirectory = "path_to_database_folder" 
};
this.documentStore.Initialize();     

После этого с хранилищем можно работать. Для добавления данных используется такой код:

lock (this.documentStore)
{
  using (var session = this.documentStore.OpenSession())
  {
    ScoreBoardResult record = session.Query<ScoreBoardResult>()
      .SingleOrDefault(r => r.Game == result.Game 
        && r.UserCode == result.UserCode);
    if (record != null)
    {
      if (record.Score < result.Score)
      {
        record.Score = result.Score;
        record.UserName = result.UserName;
        session.SaveChanges();
      }
    }
    else
    {
      session.Store(result);
      session.SaveChanges();
    }
  }
}

Здесь все просто — если в базе уже есть результат игрока, и новый результат лучше — перетираем результат. Если результата игрока нет в базе — добавляем его.
this.documentStore.OpenSession() — создание новой сессии работы с базой. Через созданную сессию происходят все обращения к базе (Unit Of Work).
session.Query() — получение данных из базы.
session.Store(result) — добавление объекта в базу.
session.SaveChanges() — сохранение результатов. В этот момент в хранилище попадут все изменения, сделанные через эту сессию.

Получение n лучших результатов еще легче:

using (var session = this.documentStore.OpenSession())
{
  return session.Query<ScoreBoardResult>()
    .OrderByDescending(r => r.Score)
    .Take(count)
    .ToList();
}

Запускаем, убеждаемся, что все работает, и чистим конфиг сервера (см. предыдущую статью). Должно остаться только это:

<system.serviceModel>
  <services>
    <service name="ScoreBoardServer.ScoreBoardService">
      <endpoint address="net.tcp://localhost:9876/"
                binding="netTcpBinding"
                contract="ScoreBoardServer.IScoreBoard" />
    </service>
  </services>
</system.serviceModel>

Впечатления от RavenDB

Очень удобно использовать. Типизированное хранилище без конфигурирования и маппинга. ORM не нужен совсем.
Встраиваемая база тормозит при инициализации. примерно секунд 5-10. Можно поднимать отдельный сервер RavenDB, но этот режим я не тестировал, возможно он будет производительнее.
Она платная. Лицензию не обязательно покупать при разработке, опенсорсные проекты могут получить лицензию бесплатно.

Полный код доски рекордов можно посмотреть на гитхабе.



На обновления блога теперь можно подписаться Вконтакте

Tags: