Сохранить данные через веб-сервис с помощью NHibernate? - PullRequest
3 голосов
/ 27 октября 2009

В настоящее время у нас есть приложение, которое получает данные с сервера через веб-сервис и заполняет DataSet. Затем пользователи API манипулируют им с помощью объектов, которые в свою очередь изменяют набор данных. Затем изменения сериализуются, сжимаются и отправляются обратно на сервер для обновления.

Однако я начал использовать NHibernate в проектах, и мне действительно нравится отдельная природа объектов POCO. Теперь у нас проблема в том, что наши объекты настолько привязаны к внутреннему DataSet, что их невозможно использовать во многих ситуациях, и в итоге мы создаем дубликаты объектов POCO для передачи туда и обратно.

Batch.GetBatch() -> calls to web server and populates an internal dataset
Batch.SaveBatch() -> send changes to web server from dataset 

Есть ли способ получить аналогичную модель, которую мы используем, когда весь доступ к базе данных происходит через веб-сервис, но с использованием NHibernate?

Редактировать 1

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

  1. Я должен сериализовать и отправить всю коллекцию, а не только измененные предметы
  2. Если я попытаюсь снова заполнить коллекцию по возвращении своих объектов, все мои ссылки будут потеряны.

Вот мой пример решения.

Клиентская сторона

public IList<Job> GetAll()
{
    return coreWebService
      .GetJobs()
      .BinaryDeserialize<IList<Job>>();
}

public IList<Job> Save(IList<Job> Jobs)
{
    return coreWebService
             .Save(Jobs.BinarySerialize())
             .BinaryDeserialize<IList<Job>>();
}

Серверная сторона

[WebMethod]
public byte[] GetJobs()
{
    using (ISession session = NHibernateHelper.OpenSession())
    {
        return (from j in session.Linq<Job>()
                select j).ToList().BinarySerialize();
    }
}

[WebMethod]
public byte[] Save(byte[] JobBytes)
{
    var Jobs = JobBytes.BinaryDeserialize<IList<Job>>();

    using (ISession session = NHibernateHelper.OpenSession())
    using (ITransaction transaction = session.BeginTransaction())
    {
        foreach (var job in Jobs)
        {
            session.SaveOrUpdate(job);
        }
        transaction.Commit();
    }

    return Jobs.BinarySerialize();
}

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

Редактировать 2

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

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

Ответы [ 2 ]

0 голосов
/ 15 апреля 2014

Я думаю, что ваша проблема вращается вокруг этой проблемы:

http://thatextramile.be/blog/2010/05/why-you-shouldnt-expose-your-entities-through-your-services/

Вы или не собираетесь отправлять ORM-сущности по сети?

Поскольку у вас сервис-ориентированная архитектура. Я (как и автор) не рекомендую эту практику.

Я использую NHibernate. Я называю эти ORM-сущности. Они модель POCO. Но у них есть «виртуальные» свойства, которые допускают ленивую загрузку.

Однако у меня также есть несколько DTO-объектов. Это также POCO. Они не имеют ленивых свойств.

Так что я много "конвертирую". Я увлажняю ORM-сущности (с помощью NHibernate) ... и затем в конечном итоге преобразую их в Domain-DTO-Objects. Да, воняет в начале.

Сервер отправляет Domain-DTO-Objects. НЕТ ленивой загрузки. Я должен заселить их моделью "Goldie Locks" "в самый раз". Ака, если мне нужны Parent (s) с одним уровнем детей, я должен знать об этом заранее и посылать Domain-DTO-Objects таким образом, с нужным количеством гидратации.

Когда я возвращаю Domain-DTO-Objects (от клиента к серверу), я должен полностью изменить процесс. Я конвертирую Domain-DTO-Objects в ORM-Entities. И разрешить NHibernate работать с ORM-сущностями.

Поскольку архитектура "отключена", я выполняю много вызовов (NHiberntae) ".Merge ()".

        // ormItem is any NHibernate poco
        using (ISession session = ISessionCreator.OpenSession())
        {
            using (ITransaction transaction = session.BeginTransaction())
            {
                session.BeginTransaction();
                ParkingAreaNHEntity mergedItem = session.Merge(ormItem);
                transaction.Commit();
            }
        }

. Мердж - замечательная вещь. Entity Framework не имеет его. Boo.

Это много настроек? Да. Я думаю, что это идеально? Нет.

Тем не менее. Поскольку я отправляю в ORM очень простые DTO (Poco), которые не «приправлены», у меня есть возможность переключать ORM, не нарушая мои контракты с внешним миром.

Мой слой данных может быть ADO.NET, EF, NHibernate или любым другим. Я должен написать «Конвертеры», если я переключаюсь, и код ORM, но все остальное изолировано.

Многие люди спорят со мной. Они сказали, что я слишком много делаю, и с ORM-сущностями все в порядке.

Опять же, мне нравится «теперь разрешать любую ленивую загрузку». И я предпочитаю, чтобы мой слой данных был изолирован. Мои клиенты не должны знать или заботиться о моем уровне данных / выборе.

Достаточно тонких различий (или некоторых не столь тонких) между EF и NHibernate, чтобы нарушить план игры.

Мои доменные DTO-объекты на 95% похожи на мои ORM-сущности? Ага. Но это те 5%, которые могут вас шокировать.

Переход от наборов данных, особенно если они заполнены хранимыми процедурами с большим количеством логики в TSQL, не является тривиальным. Но теперь, когда я делаю объектную модель и НИКОГДА не пишу хранимую процедуру, которая не является простыми функциями CRUD, я никогда не вернусь.

И я ненавижу проекты обслуживания с voodoo TSQL в хранимых процедурах. Это больше не 1999. Ну и большинство мест.

Удачи.

PS Без .Merge (в EF) вот что вам нужно сделать в отключенном мире: (Boo microsoft)

http://www.entityframeworktutorial.net/EntityFramework4.3/update-many-to-many-entity-using-dbcontext.aspx

0 голосов
/ 08 декабря 2011

Я только бегло посмотрел на ваш вопрос, так что простите, если мой ответ недальновиден, но здесь говорится:

Я не думаю, что вы можете логически уйти от сопоставления объекта домена с DTO.

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

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

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

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

...