- Щелкните правой кнопкой мыши серверный проект, выберите Добавить, а затем Новый элемент.
- В списке категорий выберите Интернет, а затем выберите шаблон Класс службы домена.
- Назовите класс BuildingDomainService.cs
- Нажмите кнопку Добавить.
- Убедитесь, что установлен флажок Разрешить клиентский доступ.
- Выберите сущность Building и Flor, а затем установите для нее флажок Разрешить изменение.
- Нажмите кнопку ОК.
- Откройте этот файл. Обратите внимание, что файл обладает следующими характеристиками.
- Были созданы методы для вставки, обновления и удаления зданий и этажей из записей.
В этой статье, мы продолжаем создавать наше бизнес приложение для отображения базы зданий. И сейчас нам необходимо добавить службу домена в проект среднего уровня. Служба домена предоставляет клиентскому проекту сущности данных и операции из серверного проекта. В службу домена можно добавить бизнес-логику для управления взаимодействием клиента с данными. Как создать службу домена в проект?
Откроется диалоговое окно Добавление нового класса службы домена.
Класс BuildingDomainService будет создан в новом файле BuildingDomainService.cs.
· Класс BuildingDomainService происходит от класса LinqToEntitiesDomainService, который является абстрактным базовым классом из платформы Службы RIA . Этот базовый класс был использован автоматически, поскольку служба домена предоставляет класс данных ADO.NET Entity.
· Универсальный базовый класс привязан к классу сущности, созданному на предыдущих шагах с помощью BuildingEntities типа ObjectContext в его универсальном параметре.
· Класс BuildingDomainService помечен атрибутом EnableClientAccessAttribute, указывающим, что он является видимым для клиентского уровня.
· Создается метод запроса с именем GetBuildings. Этот метод возвращает все элементы без фильтрации и сортировки.
Рассмотрим подробнее, что у нас получилось. Основное на что следует обратить внимание, это MetadataAttribute. Я использовала основные из них, давайте выясним что они значат.
1) Аттрибут Display - Предоставляет атрибут общего назначения, позволяющий указывать локализуемые строки для типов и членов разделяемых классов сущностей. Вот его свойства:
Имя
|
Описание
|
Получает или задает значение, указывающее, нужно ли для отображения этого поля автоматически создавать пользовательский интерфейс.
| |
Added exception.
| |
Получает или задает значение, которое используется для отображения описания пользовательского интерфейса.
| |
Получает или задает значение, используемое для группировки полей в пользовательском интерфейсе.
| |
Получает или задает значение, которое используется для отображения в элементе пользовательского интерфейса.
| |
Получает или задает порядковый вес столбца.
| |
Получает или задает значение, которое будет использоваться для задания подсказки в элементе пользовательского интерфейса.
| |
Получает или задает значение, используемое в качестве метки столбца сетки.
| |
2) Аттрибут Required - Указывает, что требуется значение поля данных. Вот его свойства.
Имя
|
Описание
|
Получает или задает значение, указывающее на то, разрешена ли пустая строка.
| |
Получает или задает сообщение об ошибке, которое необходимо связать с проверяющим элементом управления на случай сбоя во время проверки.(Унаследовано от ValidationAttribute.)
| |
Получает или задает имя ресурса сообщений об ошибках, используемого для поиска значения свойства ErrorMessageResourceType в случае сбоя при проверке. (Унаследовано от ValidationAttribute.)
| |
Получает или задает тип ресурса, используемого для поиска сообщения об ошибке в случае сбоя проверки. (Унаследовано от ValidationAttribute.)
| |
Получает локализованное сообщение об ошибке проверки. (Унаследовано от ValidationAttribute.)
| |
Остальные атрибуты, если вам понадобятся, вы без труда найдёте в msdn по этой ссылке http://msdn.microsoft.com/ru-ru/library/cc490428.aspx
namespace BuildingApp.Web.DataAccess
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
// The MetadataTypeAttribute identifies BuildingMetadata as the class
// that carries additional metadata for the Building class.
[MetadataTypeAttribute(typeof(Building.BuildingMetadata))]
public partial class Building
{
// This class allows you to attach custom attributes to properties
// of the Building class.
//
// For example, the following marks the Xyz property as a
// required property and specifies the format for valid values:
// [Required]
// [RegularExpression("[A-Z][A-Za-z0-9]*")]
// [StringLength(32)]
// public string Xyz { get; set; }
internal sealed class BuildingMetadata
{
// Metadata classes are not meant to be instantiated.
private BuildingMetadata()
{
}
[Required]
[StringLength(500)]
[Display(Order = 1, Name = "Адрес")]
public string Address { get; set; }
[Display(Order = 3, Name = "Дата постройки")]
public Nullable<DateTime> CreationDate { get; set; }
[Display(AutoGenerateField = false)]
public EntityCollection<Floor> Floor { get; set; }
[Display(Order = 2, Name = "Этажность")]
public Nullable<int> FloorCount { get; set; }
[Display(AutoGenerateField = false)]
public int ID { get; set; }
[Display(Order = 7, Name = "Макс.арендная ставка (руб.)")]
public Nullable<int> MaxRentalRate { get; set; }
[Display(Order = 6, Name = "Мин.арендная ставка (руб.)")]
public Nullable<int> MinRentalRate { get; set; }
[Required]
[StringLength(200)]
[Display(Order = 0, Name = "Название")]
public string Name { get; set; }
[Display(Order = 5, Name = "Общее кол-во помещений")]
public Nullable<int> Room { get; set; }
[Display(Order = 8, Name = "Кол-во арендаторов")]
public Nullable<int> TenantsCount { get; set; }
[Display(Order = 4, Name = "Общая площадь (кв.м)")]
public Nullable<int> TotalArea { get; set; }
}
}
// The MetadataTypeAttribute identifies FloorMetadata as the class
// that carries additional metadata for the Floor class.
[MetadataTypeAttribute(typeof(Floor.FloorMetadata))]
public partial class Floor
{
// This class allows you to attach custom attributes to properties
// of the Floor class.
//
// For example, the following marks the Xyz property as a
// required property and specifies the format for valid values:
// [Required]
// [RegularExpression("[A-Z][A-Za-z0-9]*")]
// [StringLength(32)]
// public string Xyz { get; set; }
internal sealed class FloorMetadata
{
// Metadata classes are not meant to be instantiated.
private FloorMetadata()
{
}
[Display(Order = 1, Name = "Общая площадь (кв.м)")]
public Nullable<int> Area { get; set; }
[Display(AutoGenerateField = false)]
public Building Building { get; set; }
[Display(AutoGenerateField = false)]
public int BuildingID { get; set; }
[Required]
[Editable(false, AllowInitialValue=true)]
[Display(Order = 0, Name = "Номер этажа")]
public int Number { get; set; }
[Display(Order = 2, Name = "Кол-во арендаторов")]
public Nullable<int> TenantsCount { get; set; }
}
}
}
|
Теперь рассмотрим DomainService. Наш класс BuildingDomainService содержит основные методы для работы с данными, такие как получение, вставка, обновление и удаление данных. Если нам необходима изменить их логику или добавить свои методы работы с данными, мы может это сделать в данном классе.
namespace BuildingApp.Web.DomainService
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Linq;
using System.ServiceModel.DomainServices.EntityFramework;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
using BuildingApp.Web.DataAccess;
[EnableClientAccess()]
public class BuildingDomainService : LinqToEntitiesDomainService<BuildingDBEntities>
{
// TODO:
// Consider constraining the results of your query method. If you need additional input you can
// add parameters to this method or create additional query methods with different names.
// To support paging you will need to add ordering to the 'Building' query.
public IQueryable<Building> GetBuilding()
{
return this.ObjectContext.Building;
}
public void InsertBuilding(Building building)
{
if ((building.EntityState != EntityState.Detached))
{
this.ObjectContext.ObjectStateManager.ChangeObjectState(building, EntityState.Added);
}
else
{
this.ObjectContext.Building.AddObject(building);
}
}
public void UpdateBuilding(Building currentBuilding)
{
this.ObjectContext.Building.AttachAsModified(currentBuilding, this.ChangeSet.GetOriginal(currentBuilding));
}
public void DeleteBuilding(Building building)
{
if ((building.EntityState == EntityState.Detached))
{
this.ObjectContext.Building.Attach(building);
}
foreach (Floor floor in this.ObjectContext.Floor.Where(p=>p.BuildingID == building.ID))
{
this.ObjectContext.Floor.DeleteObject(floor);
}
this.ObjectContext.Building.DeleteObject(building);
}
// TODO:
// Consider constraining the results of your query method. If you need additional input you can
// add parameters to this method or create additional query methods with different names.
// To support paging you will need to add ordering to the 'Floor' query.
public IQueryable<Floor> GetFloor()
{
return this.ObjectContext.Floor;
}
public IQueryable<Floor> GetFloorsByBuilding(int bID)
{
return this.ObjectContext.Floor.Where(p => p.BuildingID == bID);
}
public void InsertFloor(Floor floor)
{
if ((floor.EntityState != EntityState.Detached))
{
this.ObjectContext.ObjectStateManager.ChangeObjectState(floor, EntityState.Added);
}
else
{
this.ObjectContext.Floor.AddObject(floor);
//if (this.ObjectContext.Floor.Where(p => p.Number == floor.Number).Count() > 0)
//{
// this.ObjectContext.Floor.AddObject(floor);
//}
}
}
public void UpdateFloor(Floor currentFloor)
{
this.ObjectContext.Floor.AttachAsModified(currentFloor, this.ChangeSet.GetOriginal(currentFloor));
}
public void DeleteFloor(Floor floor)
{
if ((floor.EntityState == EntityState.Detached))
{
this.ObjectContext.Floor.Attach(floor);
}
this.ObjectContext.Floor.DeleteObject(floor);
}
}
}
|
Надеюсь, статья была полезной и интересной, мы уже продвинулись в создании нашего приложения довольно далеко, создали слой работы с данными, слой бизнес логики, теперь нам осталось создать слой представления, что мы и сделаем в следующей статье.
Комментариев нет:
Отправить комментарий