Создание веб-сервиса интернет-магазина

Рассмотрим пример создания веб-сервиса интернет магазина. Создаваемый веб-сервис должен выполнять такой минимальный набор функций:

Предоставлять список каталогов интернет-магазина.

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

Регистрировать заказ с указанием контактной информации заказчика, времени и адреса доставки, а также необходимых товаров и их количество.

Передавать статус заказа, сделанного заказчиком.

 

Спроектируем базу данных для хранения всех необходимых данных для работы веб-сервиса. Полученная в среде Visio физическая модель базы данных выглядит следующим образом:

Рис. 4.2. Физическая модель БД веб-сервиса.

 

Для хранения данных из базы данных в приложении веб-сервиса создадим следующий набор классов:

using System;

using System.Collections.Generic;

using BLToolkit.Mapping;

 

namespace WebShoping

{

public class Catalog

{

[MapField("CatalogId")]

public int Id;

public string Name;

}

 

public class Good

{

[MapField("GoodId")]

public int Id;

public string Name;

public double Price;

public bool Available;

}

 

public class Order

{

[MapField("OrderId")]

public Guid Id;

public string FIO;

public string Phone;

public string CardNo;

public string CardCVV2;

public string Address;

public DateTime Date;

 

public List<OrderedGood> Goods;

}

 

public class OrderedGood

{

public int Id;

public int Count;

}

 

public enum OrderStatus

{

[MapValue("R")]

Registered,

[MapValue("I")]

InWork,

[MapValue("S")]

Sended,

[MapValue("N")]

NotEnoughGoods,

[MapValue("W")]

WrongGoodId,

[DefaultValue()]

[NullValue()]

OrderNotFound

}

}

 

Как можно заметить, в приведенном выше коде используются тип данных List<OrderedGood>. Такая запись означает создание типизированного списка с типом данных OrderedGood. Возможность создания generic типов данных была введена в .NET 2.0 и за работу с ними отвечает пространство имен System.Collections.Generic.

Для работы с базой данных в создаваемом веб-сервисе используется библиотека «Business Logic Toolkit» (http://rsdn.ru/?article/files/libs/RsdnFrameworkData.xml), являющаяся проектом с открытым исходным кодом, разрабатываемом в рамках проекта RSDN. Эта библиотека берет на себя все функции по организации соединения с базой данных, исполнению запросов и отображению результатов запроса на классы приложений. В приведенном выше примере можно заметить использование атрибутов управления отображением, позволяющих установить правильное соответствие между именами атрибутов отношений базы данных и именами свойств используемых классов. Для перечисления «OrderStatus» был также задан программный кодификатор, задающий соотношение между возможными статусами заказа и значениями, хранимыми в базе данных.

Описав классы, используемые для хранения данных, можно приступить к написанию класса самого веб-сервиса:

using System;

using System.Collections.Generic;

using System.Web.Services;

using BLToolkit.Data;

 

namespace WebShoping

{

[WebService(Namespace = "http://www.shopservice.ru",

Description = "Интернет магазин")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

public class ShopService : WebService

{

/// <summary>

/// Получает список катологов магазина

/// </summary>

/// <returns>Список каталогов</returns>

[WebMethod(Description = "Получить список каталогов",

CacheDuration = 300)]

public List<Catalog> GetCatalogs()

{

using (DbManager db = new DbManager())

{

db.SetSpCommand("GetCatalogs");

return db.ExecuteList<Catalog>();

}

}

 

/// <summary>

/// Получает товары из каталога

/// </summary>

/// <param name="catalogId">Ид каталога</param>

/// <returns>Список товаров</returns>

[WebMethod(Description = "Получить список товаров в каталоге",

CacheDuration = 300)]

public List<Good> GetGoods(int catalogId)

{

using (DbManager db = new DbManager())

{

db.SetSpCommand("GetGoods",

db.Parameter("@CatalogId", catalogId));

return db.ExecuteList<Good>();

}

}

 

/// <summary>

/// Регистрирует заказ в магазине

/// </summary>

/// <param name="order">Заказ</param>

/// <param name="statusName">Статус заказа</param>

/// <returns>Cумму заказа</returns>

[WebMethod(Description = "Зарегистрировать заказ")]

public double RegisterOrder(Order order, out string statusName)

{

OrderStatus status;

double orderSum = 0;

 

using (DbManager db = new DbManager())

{

try

{

db.BeginTransaction();

 

db.SetSpCommand("SaveOrder",

db.Parameter("@OrderId", order.Id),

db.Parameter("@FIO", order.FIO),

db.Parameter("@Phone", order.Phone),

db.Parameter("@Address", order.Address),

db.Parameter("@CardNo", order.CardNo),

db.Parameter("@CardCVV2", order.CardCVV2),

db.Parameter("@Date", order.Date),

db.Parameter("@Status", db.MappingSchema.MapEnumToValue(OrderStatus.Registered)));

db.ExecuteNonQuery();

 

foreach (OrderedGood orderedGood in order.Goods)

{

db.SetSpCommand("AddOrderGood",

db.Parameter("@OrderId", order.Id),

db.Parameter("@GoodId", orderedGood.Id),

db.Parameter("@Count",orderedGood.Count));

db.ExecuteNonQuery();

}

 

db.CommitTransaction();

 

db.SetSpCommand("GetOrderSum",

db.Parameter("@OrderId", order.Id));

 

object sum = db.ExecuteScalar();

orderSum = Convert.ToDouble(sum);

 

if (orderSum < 10000)

{

status = OrderStatus.Registered;

}

else

{

status = OrderStatus.NotEnoughGoods;

 

db.SetSpCommand("UpdateOrderStatus",

db.Parameter("@OrderId", order.Id),

db.Parameter("@Status",

db.MappingSchema.MapEnumToValue(status)));

db.ExecuteNonQuery();

}

}

catch

{

// Товар не найден в базе

db.Transaction.Rollback();

status = OrderStatus.WrongGoodId;

}

}

 

statusName = status.ToString();

return orderSum;

}

 

/// <summary>

/// Получает статус заказа

/// </summary>

/// <param name="orderId">Ид заказа</param>

/// <returns>Статус</returns>

[WebMethod(Description = "Получить статус заказа")]

public OrderStatus GetOrderStatus(Guid orderId)

{

using (DbManager db = new DbManager())

{

db.SetSpCommand("GetOrderStatus",

db.Parameter("@OrderId", orderId));

object res = db.ExecuteScalar();

return (OrderStatus)db.MappingSchema.MapValueToEnum(res,

typeof(OrderStatus));

}

}

 

/// <summary>

/// Возвращает номер карты в платежной системе, на которую нужно

/// переводить деньги для оплаты в магазине

/// </summary>

/// <returns>Номер карты</returns>

[WebMethod(Description = "Возвращает номер карты магазина в платежной системе")]

public string GetCardNumber()

{

return "1234567812345678";

}

}

}

 

Для работы с базой данных в приведенном примере используется набор из пяти хранимых процедур:

· Получение списка каталогов

ALTER PROCEDURE dbo.GetCatalogs

AS

SELECT *

FROM Catalog

· Получение списка товаров в каталоге

ALTER PROCEDURE dbo.GetGoods

@CatalogId int

AS

SELECT *

FROM Good

WHERE CatalogId = @CatalogId

· Сохранение заказа

ALTER PROCEDURE [dbo].[SaveOrder]

@OrderId uniqueidentifier,

@FIO nvarchar(100),

@Phone nvarchar(100),

@Address nvarchar(200),

@CardNo char(16),

@CardCVV2 char(3),

@Date datetime,

@Status char(1)

AS

INSERT INTO [Order] (OrderId, FIO, Phone, Address,

CardNo, CardCVV2, [Date], Status)

VALUES (@OrderId, @FIO, @Phone, @Address,

@CardNo, @CardCVV2, @Date, @Status)

· Добавление товара в сохраненный заказ

ALTER PROCEDURE dbo.AddOrderGood

@OrderId int,

@GoodId int,

@Count int

AS

INSERT INTO OrderedGoods (OrderId, GoodId, [Count])

VALUES (@OrderId, @GoodId, @Count)

· Получение статуса сохраненного заказа

ALTER PROCEDURE [dbo].[GetOrderStatus]

@OrderId uniqueidentifier

AS

SELECT Status

FROM [Order]

WHERE OrderId = @OrderId

· Получение суммы сохраненного заказа

ALTER PROCEDURE [dbo].[GetOrderSum]

@OrderId uniqueidentifier

AS

SELECT SUM(o.Count * g.Price)

FROM OrderedGoods o

JOIN Good g

ON (o.GoodId = g.GoodId)

WHERE o.OrderId = @OrderId

· Изменение статуса сохраненного заказа

ALTER PROCEDURE [dbo].[UpdateOrderStatus]

@OrderId uniqueidentifier,

@Status char(1)

AS

UPDATE [Order]

SET Status = @Status

WHERE OrderId = @OrderId

 

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

Стоит отметить также атрибуты из пространства имен System.Web.Services, управляющие созданием веб-сервиса:

[WebService(Namespace = "http://www.mephi.ru/order",

Description = "Интернет магазин")]

Этот атрибут задает целевое пространство имен, в котором будет определены все типы данных созданного веб-сервиса. Вторая строка задает описание всего веб-сервиса на естественном языке.

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

Этот атрибут определяет, что создаваемый веб-сервис должен соответствовать стандарту Web Services Interoperability (WSI) Basic Profile версии 1.1 (http://www.ws-i.org/Profiles/BasicProfile-1.1.html).

[WebMethod(Description = "Получить список каталогов",

CacheDuration = 300)]

Этот атрибут задает описание операции веб-сервиса на естественном языке. Во второй строке задается длительность хранения кэша результатов работы операции в секундах. Так как веб-сервисы на платформе .NET являются подклассом веб-приложений ASP.NET, то для них также доступна вся базовая функциональность этих приложений. К примеру, кэширование результатов работы операции осуществляется на уровне веб-сервера, на котором исполняется веб-сервис. При этом кэшируются пары HTTP запросов и соответствующих им ответов.

Кэширование позволяет оптимизировать работу веб-сервисов. Оно может быть использовано при ограниченном множестве входных данных, как, например, в используемом примере, где входных данных нет. Также немаловажным фактором должна быть статичность результатов выполнения операции. В противном случае вместо актуальных данных клиент может получить устаревшие данные из кэша, что в свою очередь может привести к неверному функционированию приложений. Если перечисленные выше условия не выполняются, то использование кэширования результатов работы веб-сервиса может привести к чрезмерному расходованию памяти веб-сервера и лишь замедлит его работу.








Дата добавления: 2015-02-28; просмотров: 996;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.046 сек.