Подтвердить что ты не робот

Данные по контракту данных WCF и справочные данные?

Запрос обратной связи/варианты/комментарии относительно "наилучшего" шаблона для использования для справочных данных в моих сервисах.

Что я имею в виду под ссылочными данными?

В качестве примера можно использовать Northwind. Заказ связан с клиентом в базе данных. Когда я реализую свою службу заказов, в некоторых случаях мне нужна ссылка "полный" Клиент из заказа и другие случаи, когда я просто хочу ссылку на Клиента (например, пару "ключ/значение" ).

Например, если бы я делал GetAllOrders(), я бы не хотел возвращать полностью заполненный заказ, я бы хотел вернуть облегченную версию Ордера с только справочными данными для каждого заказа клиента. Однако, если бы я использовал метод GetOrder(), я бы, вероятно, хотел бы заполнить данные Клиента, потому что, возможно, ему нужен этот метод. Могут быть и другие ситуации, когда я могу попросить, чтобы детали клиента были заполнены во время определенных вызовов методов, но оставлены для других.

Вот что я придумал:

[DataContract]
public OrderDTO
{
    [DataMember(Required)]
    public CustomerDTO;

    //etc..
}

[DataContract]
public CustomerDTO
{
    [DataMember(Required)]
    public ReferenceInfo ReferenceInfo;

    [DataMember(Optional)]
    public CustomerInfo CustomerInfo;
}

[DataContract]
public ReferenceInfo
{
    [DataMember(Required)]
    public string Key;

    [DataMember(Required)]
    public string Value;
}

[DataContract]
public CustomerInfo 
{
    [DataMember(Required)]
    public string CustomerID;

    [DataMember(Required)]
    public string Name;

    //etc....
}

Мысль здесь состоит в том, что, поскольку ReferenceInfo (которая является общей парой Key/Value) всегда требуется в CustomerDTO, у меня всегда будет ReferenceInfo. Это дает мне достаточно информации, чтобы позже получить информацию о Клиенте, если это необходимо. Недостатком того, что CustomerDTO требует ReferenceInfo, является то, что он может быть переполнен, когда я получаю полный CustomerDTO (т.е. С заполнением CustomerInfo), но по крайней мере мне гарантируется справочная информация.

Есть ли какой-нибудь другой шаблон или фреймворк, который я могу использовать, чтобы сделать этот сценарий/реализацию "более чистым"?

Причина, по которой я спрашиваю, заключается в том, что, хотя мы могли бы просто сказать в Northwind, чтобы ВСЕГДА вернули полную CustomerDTO, которая может хорошо работать в упрощенной ситуации в Northwind. В моем случае у меня есть объект с 25-50 полями, которые являются ссылочными/поисковыми типами данных. Некоторые из них более важны для загрузки, чем другие, в разных ситуациях, но я хотел бы иметь как можно меньше определений этих ссылочных типов (чтобы я не попадал в "адский аспект DTO" ).

мнения? Обратная связь? Комментарии?

Спасибо!

4b9b3361

Ответ 1

Мы находимся в том же решении, что и наш проект. На данный момент мы решили создать три уровня DTO для обработки Thing: SimpleThing, ComplexThing и FullThing. Мы не знаем, как это сработает для нас, так что это еще не ответ, основанный на реальности.

Одна вещь, о которой мне интересно, - это узнать, что наши службы разработаны на "неправильном" уровне. Например, есть ли когда-нибудь экземпляр, где мы должны разделить FullThing и пропустить SimpleThing? Если мы это сделаем, значит ли это, что мы неправильно применяем некоторую бизнес-логику на слишком высоком уровне?

Ответ 2

Веб-сервис API рекламной рекламы Amazon - хороший пример той же проблемы, с которой вы сталкиваетесь.

Они используют разные DTO для предоставления абонентам более или менее подробной информации в зависимости от их обстоятельств. Например, существует небольшая группа ответов , большая группа ответов и в средней группе ответа отклика.

Наличие разных DTO является хорошей техникой, если, как вы говорите, вам не нужен чатный интерфейс.

Ответ 3

Мне кажется сложным решением. Почему бы просто не иметь поле идентификатора клиента в классе OrderDTO, а затем позволить приложению решать во время выполнения, нужны ли ему данные клиента. Поскольку он имеет идентификатор клиента, он может вытащить данные, когда он это решит.

Ответ 4

Я решил отказаться от подхода, который я собирался предпринять. Я думаю, что многие из моих первоначальных опасений были связаны с отсутствием требований. Я вроде как ожидал, что это так, но было любопытно посмотреть, как другие могли бы решить эту проблему, чтобы определить, когда загружать определенные данные, а когда нет.

Я сжимаю свой контракт с данными, чтобы содержать наиболее используемые поля элементов опорных данных. Это должно работать для большинства потребителей. Если предоставленных данных недостаточно для данного потребителя, у них будет возможность запросить отдельную службу, чтобы отбросить полную информацию для конкретной ссылочной единицы (например, Валюта, Состояние и т.д.). Для простых поисков, которые действительно являются в основном парами Key/Value, мы будем обрабатывать их с помощью общего контракта данных Key/Value. Я мог бы даже использовать атрибут KnownType для более специализированных пар Key/Value.

[DataContract]
public OrderDTO
{
    [DataMember(Required)]
    public CustomerDTO Customer;

    //in this case, I think consumers will need currency data, 
    //so I pass back a full currency item
    [DataMember(Required)]
    public Currency Currency; 

    //in this case, I think consumers are not likely to need full StateRegion data, 
    //so I pass back a "reference" to it
    //User can call a separate service method to get full details if needed, or 
    [DataMember(Required)]
    public KeyValuePair ShipToStateRegion;

    //etc..
}


[DataContract]
[KnownType(Currency)]
public KeyValuePair
{
    [DataMember(Required)]
    public string Key;

    [DataMember(Required)]
    public string Value;

    //enum consisting of all possible reference types, 
    //such as "Currency", "StateRegion", "Country", etc.
    [DataMember(Required)]
    public ReferenceType ReferenceType; 
}


[DataContract]
public Currency : KeyValuePair
{
    [DataMember(Required)]
    public decimal ExchangeRate;

    [DataMember(Required)]
    public DateTime ExchangeRateAsOfDate;
}


[DataContract]
public CustomerDTO 
{
    [DataMember(Required)]
    public string CustomerID;

    [DataMember(Required)]
    public string Name;

    //etc....
}

Мысли? Мнения? Комментарии?

Ответ 5

Мы столкнулись с этой проблемой и в объектно-реляционном сопоставлении. Есть ситуации, когда нам нужен полный объект и другие, где мы хотим получить ссылку на него.

Трудность состоит в том, что, выпекая сериализацию в самих классах, шаблон datacontract обеспечивает идею о том, что существует только один правильный способ сериализации объекта. Но есть много сценариев, где вы можете частично сериализовать класс и/или его дочерние объекты.

Это обычно означает, что для каждого класса необходимо иметь несколько DTO. Например, FullCustomerDTO и CustomerReferenceDTO. Затем вам нужно создать способы сопоставления различных DTO с объектом домена Customer.

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

Ответ 6

Еще одна возможность - рассматривать объекты как имущественные мешки. Укажите нужные свойства при запросе и верните именно те свойства, которые вам нужны.

Изменение свойств, отображаемых в "короткой" версии, не потребует нескольких обращений в оба конца, вы можете получить все свойства для набора за один раз (избегая чат-интерфейсов), и вам не нужно изменять ваши данные или операционные контракты, если вы решите, что вам нужны разные свойства для "короткой" версии.

Ответ 7

Я обычно создаю ленивую загрузку для своих сложных веб-сервисов (т.е. веб-сервисов, отправляющих/получающих объекты). Если у Человека есть свойство Отца (также Лицо), я посылаю только идентификатор Отца вместо вложенного объекта, тогда я просто убеждаюсь, что у моего веб-службы есть операция, которая может принять идентификатор и ответить соответствующим сущностью Person, Затем клиент может вызвать веб-службу, если хочет использовать свойство Отца.

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