Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

WCF RIA Services. Предисловие. Часть 1

Anna | 17.06.2014 | нет комментариев

От переводчика

В данном цикле переводов присутствует отличная доля, добавленная лично мною, так как в оригинале применяется устаревшая VS, а так же пропущены некоторые, на мой взор значимые моменты, без которых усвоение материала крепко усложняется. Поехали.

Осмотрительно. Много картинок!

Введение

Представьте, что Вам нужно сделать солидное бизнес приложение, заказчик которого оперирует большинством данных, распределенных в разных местах, и которые обязаны каким-то образом собираться. Для реализации такой задачи Вам будет нужно исследовать ряд новых спецтехнологий и подходов, написать кучу кода, отладка. А что в выводе? Если дерзко — то легко пересылка данных с серверной части приложения в клиентскую и обратно. Ну и работа с БД. А на что бы Вы хотели сфокусироваться в первую очередь? На реализации пересылки данных? Либо на логике обработки, манипулирования, представления этих данных? Думаю, Вы предпочтете второе.

WCF RIA Services предлагает автоматизацию пересылки данных и создания многоуровневых приложения на основе Silverlight, фокусируя внимание разработчика именно на логике работы. Вы пишите только один раз экземпляр серверного кода, а он механически переносится и становится доступным на клиентской стороне, без необходимости ручного дублирования либо использования других ухищрений со стороны разработчика. Так же на заказчике остаются доступны все серверные вероятности, такие как валидация, права доступа и многие др.

В этом цикле статей Вы ознакомитесь с основными вероятностями WCF RIA Services, увидите на практике какие превосходства предоставляет применение данного подхода. На диаграме ниже показано, за что именно отвечает WCF RIA Services:
image

сегодня воспользуемся стандартным, самым простым образцом Silverlight. В последующих частях будем наращивать наши познания путем доработки приложения и применения новых методологий, тактик и спецтехнологий, одними из которых будет паттерн Model-View-ViewModel (MVVM) и модульное тестирование (unit testing).

Задачи, решаемые создаваемым приложением

Легко электронный блокнот, в тот, что дозволено заносить событие, давать ему наименование, исполнителя, план, дату начала и окончания. В всеобщем ничего трудного либо странного, впрочем отменное осознавание того, ЧТО необходимо сделать только облегчит осознавание того КАК это сделать в рамках постигаемой спецтехнологии.

Постигаемые аспекты WCF RIA Services:

  • Project Links (ссылки между планами) – связь между клиентским Silverlight планом и серверным вэб приложением либо классом библиотеки. Серверный план определяет либо создает ссылки на доменные службы, сущности, метаданные, а так же предоставляет механизм, вследствие которому код, определенный на сервере доступен заказчику. Вследствие ссылке каждый нужный заказчику код генерируется динамически во время компиляции.
  • Domain Services (доменные службы) – ядро WCF RIA Services. Они определяют доступные для выполнения на сервере операции. В основном они сводятся к CRUD (запись, чтение, обновление, удаление), впрочем могут быть и всякими другими, которые Вы сочтете надобными. Все эти операции доступны механически на стороне заказчика вследствие WCF, причем заказчику не необходимо знать о серверной стороне фактически ничего.
  • Entities (сущности) – Вам нужно определить типы сущностей на серверной стороне, а клиентская часть будет ими оперировать вследствие механической кодогенерации. Так же допустимо применение валидации и других метаданных. Типы сущностей на стороне сервера и заказчика применяются для операций сериализации/десериализации, при передаче данных между ними. Сущности могут быть сделаны с поддержкой Entity Framework, LINQ to SQL, либо Plain Old CLR Objects (POCO).
  • Domain Context (контекст домена) – клиентский аналог доменных служб. Автогенерирует код, вследствие которому получаете доступ к функционалу серверной части. Содержит внутри себя WCF proxy, тот, что предоставляет вероятность вызова обслуживания, а так же управляет запросами, которые обязаны будут выполниться на серверной стороне, отслеживает метаморфоза сущностей и многое другое.
  • DomainDataSource — это объект источника данных, тот, что применяется для выполнения запросов и уведомления сервера об внесенных изменениях. Облегчается прямое связывание в XAML и не только.

Шаг 1: Создаем Silverlight приложение и ссылку на серверную часть.

Воспользуемся примитивный БД, которая будет сберегать задания, а также всю сопутствующую информацию. Для этого нужно будет запустить скрипт TaskManager.sql, находящийся в коне плана, сделать БД и схему, заполнить БД исходными значениями.

Сделайте новейший план с именем «TasksManager». Вероятность применять WCF RIA Services присуща любому типу Silverlight приложений. Впрочем начнем с самого простого и предпочтем образец «Приложение Silverlight».

Позже нажатия на кнопку ОК, откроется следующее диалоговое окно, в котором нужно добавить птичку на «Включить службы WCF RIA».

Вследствие ей создадутся нужные ссылки на серверный план, появится кодогенерация и остальные функции, описанные ранее.
Нажимаем ОК и ожидаем создания плана.

Шаг 2: Создаем Domain Model Entities

Так как WCF RIA Services в основном предуготовлен для перемещения данных туда/сюда от заказчика к серверу и обратно, Вам потребуются некоторые модели данных данные. Из коробки поддерживается Entity Framework. Впрочем существует вероятность применять LINQ to SQL в WCF RIA Services Toolkit. Если сделать свой доменный сервис, то дозволено трудиться с POCO. Теперь воспользуемся стандартным Entity Framework.

Оригиал TaskManager.sql

USE [master]
GO

/****** Object:  Database [TaskManager]    Script Date: 06/06/2010 18:01:49 ******/
IF  EXISTS (SELECT name FROM sys.databases WHERE name = N'TaskManager.mdf')
DROP DATABASE [TaskManager.mdf]
GO

CREATE DATABASE [TaskManager.mdf]
GO

USE [TaskManager.mdf]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[User](
	[UserId] [int] IDENTITY(1,1) NOT NULL,
	[Username] [nvarchar](250) NOT NULL,
	[Password] [nvarchar](250) NOT NULL,
 CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
	[UserId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Customer](
	[CustomerId] [int] IDENTITY(1,1) NOT NULL,
	[CustomerName] [nvarchar](250) NOT NULL,
 CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED 
(
	[CustomerId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Project](
	[ProjectId] [int] IDENTITY(1,1) NOT NULL,
	[ProjectName] [nvarchar](250) NOT NULL,
	[Description] [nvarchar](max) NULL,
	[CustomerId] [int] NULL,
 CONSTRAINT [PK_Project] PRIMARY KEY CLUSTERED 
(
	[ProjectId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Task](
	[TaskId] [int] IDENTITY(1,1) NOT NULL,
	[TaskName] [nvarchar](250) NOT NULL,
	[Description] [nvarchar](max) NULL,
	[StartDate] [datetime] NULL,
	[EndDate] [datetime] NULL,
	[CustomerId] [int] NULL,
	[ProjectId] [int] NULL,
	[UserId] [int] NULL,
 CONSTRAINT [PK_Task] PRIMARY KEY CLUSTERED 
(
	[TaskId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UsersTasks](
	[TaskId] [int] NOT NULL,
	[UserId] [int] NOT NULL,
 CONSTRAINT [PK_UsersTasks] PRIMARY KEY CLUSTERED 
(
	[TaskId] ASC,
	[UserId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TimeEntry](
	[TimeEntryId] [int] IDENTITY(1,1) NOT NULL,
	[StartTime] [datetime] NOT NULL,
	[EndTime] [datetime] NOT NULL,
	[TaskId] [int] NOT NULL,
	[Description] [nvarchar](max) NOT NULL,
 CONSTRAINT [PK_TimeEntry] PRIMARY KEY CLUSTERED 
(
	[TimeEntryId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Project]  WITH CHECK ADD  CONSTRAINT [FK_Project_Customer] FOREIGN KEY([CustomerId])
REFERENCES [dbo].[Customer] ([CustomerId])
GO
ALTER TABLE [dbo].[Project] CHECK CONSTRAINT [FK_Project_Customer]
GO
ALTER TABLE [dbo].[Task]  WITH CHECK ADD  CONSTRAINT [FK_Task_Customer] FOREIGN KEY([CustomerId])
REFERENCES [dbo].[Customer] ([CustomerId])
GO
ALTER TABLE [dbo].[Task] CHECK CONSTRAINT [FK_Task_Customer]
GO
ALTER TABLE [dbo].[Task]  WITH CHECK ADD  CONSTRAINT [FK_Task_Project] FOREIGN KEY([ProjectId])
REFERENCES [dbo].[Project] ([ProjectId])
GO
ALTER TABLE [dbo].[Task] CHECK CONSTRAINT [FK_Task_Project]
GO
ALTER TABLE [dbo].[UsersTasks]  WITH CHECK ADD  CONSTRAINT [FK_UsersTasks_Task] FOREIGN KEY([TaskId])
REFERENCES [dbo].[Task] ([TaskId])
GO
ALTER TABLE [dbo].[UsersTasks] CHECK CONSTRAINT [FK_UsersTasks_Task]
GO
ALTER TABLE [dbo].[UsersTasks]  WITH CHECK ADD  CONSTRAINT [FK_UsersTasks_User] FOREIGN KEY([UserId])
REFERENCES [dbo].[User] ([UserId])
GO
ALTER TABLE [dbo].[UsersTasks] CHECK CONSTRAINT [FK_UsersTasks_User]
GO
ALTER TABLE [dbo].[TimeEntry]  WITH CHECK ADD  CONSTRAINT [FK_TimeEntry_Task] FOREIGN KEY([TaskId])
REFERENCES [dbo].[Task] ([TaskId])
GO
ALTER TABLE [dbo].[TimeEntry] CHECK CONSTRAINT [FK_TimeEntry_Task]
GO

SET NUMERIC_ROUNDABORT OFF
GO
SET XACT_ABORT, ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT, QUOTED_IDENTIFIER, ANSI_NULLS ON
GO
/*Pointer used for text / image updates. This might not be needed, but is declared here just in case*/
DECLARE @pv binary(16)
BEGIN TRANSACTION
SET IDENTITY_INSERT [dbo].[Task] OFF
SET IDENTITY_INSERT [dbo].[Task] ON
INSERT INTO [dbo].[Task] ([TaskId], [TaskName], [Description], [StartDate], [EndDate], [CustomerId], [ProjectId]) VALUES (1, N'Create Project', N'Create a Silverlight Application project with a RIA Services link', '20100601 00:00:00.000', '20100602 00:00:00.000', NULL, NULL)
INSERT INTO [dbo].[Task] ([TaskId], [TaskName], [Description], [StartDate], [EndDate], [CustomerId], [ProjectId]) VALUES (2, N'Define Data Model', N'Create an Entity Framework model for the application data', '20100602 00:00:00.000', '20100603 00:00:00.000', NULL, NULL)
INSERT INTO [dbo].[Task] ([TaskId], [TaskName], [Description], [StartDate], [EndDate], [CustomerId], [ProjectId]) VALUES (3, N'Define domain service', N'Create a domain service to expose task data to the client', '20100603 00:00:00.000', '20100604 00:00:00.000', NULL, NULL)
INSERT INTO [dbo].[Task] ([TaskId], [TaskName], [Description], [StartDate], [EndDate], [CustomerId], [ProjectId]) VALUES (4, N'Use data in the Silverlight client', N'Use the DomainContext and DomainDataSource to access and manipulate the data in the client', '20100604 00:00:00.000', '20100605 00:00:00.000', NULL, NULL)
SET IDENTITY_INSERT [dbo].[Task] OFF
COMMIT TRANSACTION

Но перед тем, как сделать Domain Model Entities, нужно сделать БД и заполнить ее.
Для этого необходимо добавить в серверной части (с приставкой .Web) папку «App_Data»:

Двойственный клик по сделанной БД «Database*.mdf». Откроется окно. Выбираем в нем вновь «Database*.mdf», правой кнопкой — «Новейший запрос». Откроется редактор запросов. Открываем TasksModel.sql, про тот, что теснее говорилось и копиреум от туда все, за исключением первых таких строк:

USE [master]
GO

/****** Object:  Database [TaskManager]    Script Date: 06/06/2010 18:01:49 ******/
IF  EXISTS (SELECT name FROM sys.databases WHERE name = N'TaskManager.mdf')
DROP DATABASE [TaskManager.mdf]
GO

CREATE DATABASE [TaskManager.mdf]
GO

USE [TaskManager.mdf]
GO

Нажимаем на кнопку «Исполнить». Все. БД заполнена таблицами, а таблица Tasks заполнена данными.

Жмем правой кнопкой мыши по TaskManager.Web и выбираем «Добавить»-«Сделать элемент». Выбираем вкладку «Данные» в левом окне, а в правом выбираем «Модель ADO.NET EDM». Даем имя “TasksModel.edmx“.

Добавить. Откроется диалоговое окно Мастер моделей EDM. Выбираем надобную БД, даем имя сущности «TaskManagerEntities» и кликаем Дальше.

На дальнейшем шаге выбираем галочкой таблицы. Даем имя модели «TaskManagerModel», а так же ставим галочку на «Формировать имена объектов во множественном либо исключительном числе»

Вуаля. Сейчас у Вас имеется модель данных Entity Framework для всех таблиц в БД. Впрочем в этом уроке вы будете трудиться только с таблицей «Task», впрочем дальше таблицы будут добавляться.

Постройте решение, что б удостовериться, что все сделано верно.

Позже создания EDM — вам должно открыться окно дизайнера.Если оно механически не открылось, то двойственный клик в Обозревателе решения по TasksModel.edmx. Дальше кликаем по пустой области. И переходим в окно свойств. Меняем параметр«Тактика создания кода» с «Нет» на «По умолчанию». Пересобираем.

Сейчас Пришло время сделать службу домена.

Шаг 3: Создание Domain Service

Теперь сотворим ядро RIA Services — службу домена. Правой кнопкой на серверной части: TaskManager.Web – «Добавить»-«Сделать элемент». Выбираем в левом окне категория «Веб», а справа «Класс DomainService». Даем имя “TasksDomainService“.

Позже нажатия на кнопку Добавить, переходим в окно настроек службы. Так как теперь будем трудиться только с таблицей Tasks — выбираем ее. В столбце «Включить редактирование» галочка не необходима. Пока. Если ее поставить то получите комплект CRUD. Если нет – то только Get (чтение). Жмем ОК.

Сделанный код, без коментариев будет выглядеть так:

    [EnableClientAccess()]
    public class TasksDomainService : LinqToEntitiesDomainService<TasksModelEntities>
    {
        public IQueryable<Task> GetTasks()
        {
            return this.ObjectContext.Tasks;
        }
    }

Класс LinqToEntitiesDomainService предоставляет связь между моделью EDM и службами WCF RIA. Признак «EnableClientAccess» указывает на то, что данный способ нужно добавить в клиентскую часть во время механической кодогенерации. В данном случае получили только способ чтения данных из таблицы, впрочем дозволено реализовать полновесный CRUD либо всякие другие действия над данными, которые Вам будут необходимы, и которые в результате так же будут доступны в клиентском плане. Как это делать разглядим больше детально в следующих статьях.

Так же запомните, что применяются конвенции, которые относятся к типу возвращаемого значения(Queryable) и правилам именования(GetName). В данном случае имеем делегированную сущность модели данных ObjectContext, которая создается как часть базового класса и применяется для извлечения каждой таблицы Tasks. Вы так же можете улучшить данный запрос добавив сортировку, фильтры и т.д., впрочем пока возвращаемое значение имеет тип IQueryable, WCF RIA Services понимает это и формирует соответствующие способы, которые дозволят применять данный функционал на стороне заказчика.

Перестроим план, чтоб удостовериться, что все сделано верно. В клиентском плане, при нажатии на иконку 2-х листиков «Показать все файлы» — должен возникнуть файл с именем TaskManager.Web.g.cs, тот, что и содержит сгенерированный код для заказчика.

Шаг 4: Приобретение данных в UI применяя DomainDataSource

Сегодня воспользуемся такой вероятность WCF RIA Services, как «drag and drop», применяя DomainDataSource непринужденно в UI. В следующих частях разглядим так же паттерн MVVM, как его применять в WCF RIA, а так же как при таком подходе применять DomainDataSource.

Выходит, откройте MainPage.xaml. Дальше откройте окно Источники данных. А сейчас перетащите Tasks в графический редактор страницы на белое поле. Исправьте размещение. Все. В разделе XAML увидите сделанный код для элемента Grid.

Строим и запускаем приложение. И наслаждаемся схожим видом:

Видео для этого урока

Исходники

На Github

Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB