Wednesday, November 11, 2009

Silverlight RIA Services. Вопросы и ответы

Просматривая дискуссии на форумах, посвященных Silverlight, часто вижу одни и те-же вопросы, на которые ответов нет. Толи потому-что знающие люди ленятся отвечать, толи считают это само-собой разумеющимся.

Итак, я попробую ответить на эти вопросы в этой статье.

Вопрос 1. Можно ли получить доступ к произвольным данным в приложении RIA Services?

Что бы ответить на этот вопрос, необходимо совершить небольшой экскурс в архитектуру приложения. В большинстве случаев RIA Silverlight приложение состоит из двух частей: клиентской части и серверной части. в каждой из частей за доступ к данным отвечает свой класс: в серверной части – наследник DomainService, а в клиентской части – наследник DomainContext. При этом нужно понимать, что DomainContext является proxy классом, который генерируется VisualStudio автоматически, после изменения и перекомпиляции DomainService класса. Таким образом, забота разработчика состоит в том, чтобы определить состав данных, методы, реализующие выборку данных, а также, если нужно, методы выполняющие изменение данных. И еще, DomainService классов может быть как несколько, так и один.

Итак, начнем с определения состава данных. Состав данных определяется с помощью классов-сущностей (entity). При описании классов нужно придерживаться определенных правил:

  1. поля или свойства классов должны иметь один из сериализумых типов: символьные, числовые, логические и т.д.
  2. в состав передаваемых данных входят только public поля или свойства.
  3. Как минимум одно поле или свойство класса должно быть помечено атрибутом [Key].

Пример определения такого класса:

public class ClientClass
{
[Key]
public Guid ID { get; set; }
[Display(Name = "Наименование клиента", Description = "Поле для ввода наименования клиента")]
[StringLength(100, ErrorMessage = "Не больше 100 символов")]
public string Name { get; set; }
}

Свойства класса могут быть декорированы атрибутами из пространства имен System.ComponentModel.DataAnnotaion. Это декорирование определяет поведение визуальных компонентов, например DataForm в клиентской части приложения.


Второй этап – реализация методов выбора данных. Здесь также существуют довольно простые правила. Методы должны возвращать класс, который имеет реализацию интерфейса IQueryable, и методы должны быть членами класса – наследника DomainService. Примеры определения методов:

public List<GeneralInfo> GetInfo(DateTime dt)
public Collection<CreditRow> GetRows(DateTime dtb)
public IQueryable<CreditDetail> GetDetails(Guid RowID)


Как реализуется собственно выборка данных, из каких источников, с применением каких технологий – выбор разработчика. Могут быть применены сервисы WCF, вебсервисы, произвольные СУБД, вообще что угодно. Дело разработчика выбрать данные, сформировать из них один или несколько экземпляров класса-сущности и поместить их в результат.

Необходимо отметить еще один способ доступа к данным, который может быть применен в том случае, если необходимо вернуть, например, количество элементов в выборке. Заводить класс-сущность с одним единственным полем невыгодно, поэтому в этом случае можно применять сервисные операции. Что же такое сервисные операции? Это методы класса DomainService, которые помечены атрибутом [ServiceOperation], и которые могут возвращать простой тип. Пример объявления и реализации такого метода:

[ServiceOperation]
public int GetCount(DateTime dt)
{
return GetRows(dt).Count;
}
естественно, сервисные операции могут применятся не только для выбора данных, выбор данных – одна из возможных областей применения.

Третий этап – реализация методов редактирования данных. DomainService поддерживает три вида изменения данных:

  • Добавление
  • Редактирование
  • Удаление.

Разработчик должен реализовать соответствующие методы. Рассмотрим, как это делается. Чтобы класс знал, какие методы должны быть вызваны в случае редактирования или удаления эти методы должны быть объявлены в соответствии с соответствующими правилами. Правила таковы:

  • Для операции добавления название метода должно начинаться с префикса Add или Insert, либо метод должен быть помечен атрибутом [Insert]
  • Для операции редактирования название метода должно начинаться с префикса Update, либо метод должен быть помечен атрибутом [Update]
  • Для операции удаления название метода должно начинаться с префикса Delete, либо метод должен быть помечен атрибутом [Delete]

единственным параметром всех этих методов должен иметь тип соответствующего класса-сущности. То есть объявление метода, которые редактирует сущность будет выглядить примерно так:

public void UpdateOrderClass(OrderClass order)

Реализация методов – на усмотрении разработчика. Закончив все три этапа, можно сказать, что организация доступа к произвольным данным завершена.


Вопрос 2. У меня есть несколько таблиц в базе данных, я организовал доступ к данным с помощью ADO.NET Entity Model. Но мне нужно передать в клиентскую часть результат запроса, объединяющий две таблицы, причем не все поля из таблиц. Как это сделать?

Ответ находится в ответе на первый вопрос. Нужно объявить класс-сущность, в которой будут все необходимые поля и поместить результат запроса в экземрляры этого класса.

Вопрос 3. Когда я разрабатываю приложение, то под ASP.NET Development server у меня все работает, но когда я размещаю приложение на хостинге или на “боевом” сервере, то приложение в браузер загружается, а данных нет, никаких ошибок не видно. Что делать?

Ответ в том, что каждый раз надо рабираться с ситуацией. Основных причин, по крайней мере, две. Первая - приложение в IIS не сконфигурировано таким образом, чтобы запросы, ответы были в кодировке utf-16. Нигде об этом в прямую не написано, но это так.

Вторая причина кроется в серверной части. Скорее всего там происходит исключение, которой с успехом “проглатывается” и соответственно никаких данных в клиента не передается. Для того, что бы отловить – нужно сделать трассировку действий вашей серверной части, что бы отловить то исключение и то место, где оно возникает.

Вопрос 4. Что нужно, чтобы развернуть RIA Siverlight приложение?

Ответ прост. Нужен .NET Framework 3.5 SP1 Runtime, IIS6, IIS7, IIS7.5. Для IIS6 нужно прописать MIME типы для .xap, xaml. и xbap.

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

2 comments:

Unknown said...

по вопросу 2: на все join-ы классов не напасешься. можно использовать атрибут [Include] для метаданных

Eugene Danilenko said...

Да, конечно, можно и так. Но это не всегда удобно