Доска рекордов на WCF и RavenDB. Хранение данных
В предыдущей части мы сделали сервис. Теперь напишем для него прокси, который будет использоваться в клиентском коде. Прокси для 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, но этот режим я не тестировал, возможно он будет производительнее.
Она платная. Лицензию не обязательно покупать при разработке, опенсорсные проекты могут получить лицензию бесплатно.
Полный код доски рекордов можно посмотреть на гитхабе.