powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / EF, Repository, UnitOfWork
14 сообщений из 164, страница 7 из 7
EF, Repository, UnitOfWork
    #38115179
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lord British, Эрик Эванс фанат-теоретик DDD, хотя для общего ознакомления не воспрещается, конечно. Больше всего опасен фанатизм, видится мне.
Простой слабоствязный компонент: ApplicationUI + ApplicationLayer + InfrastructureLayer. Меняешь свой ApplicationLayer на что-то другое, ApplicationUI продолжает так же работать.
...
Рейтинг: 0 / 0
EF, Repository, UnitOfWork
    #38115188
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ошибка, конечно же IDataService в MVC контроллере.

Код: c#
1.
2.
3.
4.
public class BaseController : Controller
{
    public IDataService Service { get; private set; }
}
...
Рейтинг: 0 / 0
EF, Repository, UnitOfWork
    #38115884
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lord BritishВ этом примере хоть я и брякнул, что

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


На деле из задействованных в примере сервисов при таких вызовах

авторvar systemLike1cResponse = _systemLike1C.SyncPaymentData(new SystemLike1CSpecificParameter());

var notifyResponse = _notificationService.Notify(new NotificationSystemSpecificParameter());

var stockResponse = _stockSystem.StartReservationProcess(new StockSystemSpecificParameter());


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

дле сервиса оплаты (что-то вроде банк клиента?) - надо получить возможно еще какие-то данные от платежной системы и т. п.. потому одной очередью тут не отделаться.

для сервиса синхронизации с 1С или ей подобной - я даже не знаю что это за процесс, но уверен он долгоиграющий и данные от 1С тоже нужны

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

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

Опять же цель примера была посмотреть какая логика каком слою относится. Но теперь итересно уже другое - вот те моменты что описаны выше.

Это прокатит для всех процессов, которые я перечислил, мало того, пригодно только отложенное выполнение, но для этого нужны очереди сообщений.
Реальные варианты:
- клиент приходит и оплачивает товары или услуги, ему мало интересно ждать и никто не будет держать его на время передачи данных в другие системы(нет соединения, идет закрытие месяца в 1С или накатываются изменения). Или если проблемы в одной из систем, то все остальные бизнес-процессы могут выполнятся тк в большинстве случаев они независимы(например, кладовщики для отправки груза после оплаты, могут даже не знать, что отправлялось сообщение о получении оплаты, а клиенту гораздо важнее полученный груз).
Из того, что доводилось делать по подобной схеме в трех разных проектах(использовалась связка nCQRS c вправленными мозгами и nServiceBus):
- обмен данными между распределенными БД и другими системами
- запуск бизнес-процессов, получение данных из внешних систем

В контроллере добавляется одна строчка CommadBus.Send(new PaymentCommad(payment));
Дальше нужно создать агрегированный домен и независимые обработчик событий. Поскольку в большинстве вариантов они независимы друг от друга, то это позволяет расширять систему с горизонтальным ростом сложности, а не вертикальным с перелопачиванием всего кода.
Рекомендую CQRS Journey
. Есть отличный букварь в том числе на русском и код с реальным примером.
...
Рейтинг: 0 / 0
EF, Repository, UnitOfWork
    #38116126
Lord British
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SeVa,

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

Отдельное спасибо за ссылку, поставил в список на изучение. Как изучу, отыщу вас тут на форуме. Буду вопросы задавать.
...
Рейтинг: 0 / 0
EF, Repository, UnitOfWork
    #38127979
SerP1983
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2SeVa: киньте ссылку пожалуйста на "отличный букварь в том числе на русском", чего-то не нашел
...
Рейтинг: 0 / 0
EF, Repository, UnitOfWork
    #38128292
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SerP19832SeVa: киньте ссылку пожалуйста на "отличный букварь в том числе на русском", чего-то не нашел

Видел только в печатном варианте(MIcrosoft Press)
...
Рейтинг: 0 / 0
EF, Repository, UnitOfWork
    #38141972
maratoss
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В попытках понять UoW + Repository возник небольшой вопросик, как быть в такой ситуации?
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
public Add(A a)
{
   using (var uow = MyFakeUnitOfWorkFactory.Create())
   {
       var repo = uow.GetRepository<A>();
       repo.Insert(a);
       uow.SaveAllChanges();
   }
}
public Bind(A a, B b)
{
   using (var uow = MyFakeUnitOfWorkFactory.Create())
   {
       var repo = uow.GetRepository<C>();
       var c = new C { A = a , B = b};
       repo.Insert(c);
       uow.SaveAllChanges();
   }
}
public BindAndCreateIfNotExist(A a, B b)
{
   using (var uow = MyFakeUnitOfWorkFactory.Create())
   {
       var repo = uow.GetRepository<A>();
       if (!repo.IsExist(a))
       {
           Add(a);
       }
       Bind(a, b); // ??? как откатить изменения Add(a), если тут произошел exception?
       uow.SaveAllChanges();
   }
}
...
Рейтинг: 0 / 0
EF, Repository, UnitOfWork
    #38142109
Lord British
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maratoss,

не щекоча кишки EF никак, если хочется этой абстракции можно в интерфейс IUnitOfWork ввести метод Undo() или как вы его назавете и в реализации EfUnitOfWork реализовать метод. Я так и не понял выгоды от введения своих интерфейсов, (кроме тестирования с фэйко контекстами) в сложном приложении с поддержкой optimistic concurency и т. п.. это все выродится в исходные реализации EF context,dbset.

поделитесь впечатлением от подхода по окончанию... интересно почитать.
...
Рейтинг: 0 / 0
EF, Repository, UnitOfWork
    #38142823
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lord Britishmaratoss,

не щекоча кишки EF никак, если хочется этой абстракции можно в интерфейс IUnitOfWork ввести метод Undo() или как вы его назавете и в реализации EfUnitOfWork реализовать метод. Я так и не понял выгоды от введения своих интерфейсов, (кроме тестирования с фэйко контекстами) в сложном приложении с поддержкой optimistic concurency и т. п.. это все выродится в исходные реализации EF context,dbset.

поделитесь впечатлением от подхода по окончанию... интересно почитать.


Undo\Redo должен быть в моделе. Модель должна быть комплексной в виде графа, тогда не будет костылей а'la BindAndCreateIfNotExist(A a, B b).
О том как это сделано без собственных лисапедов можно почитать и посмотреть в csla
...
Рейтинг: 0 / 0
EF, Repository, UnitOfWork
    #38142901
Lord British
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SeVa,

наверное это зависит про какое undo/redo ведется речь, если ему при редактировании отдельной ентити надо отменить что-то IEditableObject есть, а если ему что-то вроде Rollback или Revert в противовес SaveChanges это уже другое. Я о последнем писал, помоему ему это надо.
...
Рейтинг: 0 / 0
EF, Repository, UnitOfWork
    #38142919
maratoss
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lord Britishнаверное это зависит про какое undo/redo ведется речь, если ему при редактировании отдельной ентити надо отменить что-то IEditableObject есть, а если ему что-то вроде Rollback или Revert в противовес SaveChanges это уже другое. Я о последнем писал, помоему ему это надо.

Да, хотел узнать,
в ситуации когда метод вызывает другие два, каким образом можно выполнить их в одной транзакции, чтобы можно было сделать rollback, если что-то пошло не так.

SeVaО том как это сделано без собственных лисапедов можно почитать и посмотреть в csla
Сейчас посмотрим.
...
Рейтинг: 0 / 0
EF, Repository, UnitOfWork
    #38142998
Lord British
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maratossLord Britishнаверное это зависит про какое undo/redo ведется речь, если ему при редактировании отдельной ентити надо отменить что-то IEditableObject есть, а если ему что-то вроде Rollback или Revert в противовес SaveChanges это уже другое. Я о последнем писал, помоему ему это надо.

Да, хотел узнать,
в ситуации когда метод вызывает другие два, каким образом можно выполнить их в одной транзакции, чтобы можно было сделать rollback, если что-то пошло не так.



если вопрос только технический касаемо EF, то так
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;

namespace ConsoleApplication14
{
    class Program
    {
        static void Main(string[] args)
        {
            var txOpt = new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted };
            using (var tx = new TransactionScope(TransactionScopeOption.RequiresNew, txOpt))
            {
                Method1();
                Method2();

                // Не вызовите сomplete, будет rollback на уровне ресурсов, которые участвовали в ambient транзакции
                tx.Complete();
            }
        }

        protected static void Method1()
        {
            using (var ctx = new DB1Entities())
            {
                var t1 = ctx.T1.First(o => o.ID == 1);
                t1.NAME = 3;

                // Участвует в ambient транзакции, если Enlist = true, иначе свою создаст
                ctx.SaveChanges();
            }
        }

        protected static void Method2()
        {
            using (var ctx = new DB1Entities())
            {
                var t1 = ctx.T1.First(o => o.ID == 2);
                t1.NAME = 4;

                // Работает на уровне контекста
                if (...)
                    ctx.RevertAllChanges();

                // Участвует в ambient транзакции, если Enlist = true, иначе свою создаст
                ctx.SaveChanges();
            }
        }
    }

    public static class EfHelper
    {
        public static void RevertAllChanges(this DbContext ctx)
        {
            foreach (var entry in ctx.ChangeTracker.Entries())
                entry.State = EntityState.Unchanged;
        }
    }
}


...
Рейтинг: 0 / 0
EF, Repository, UnitOfWork
    #38143016
Lord British
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maratoss, состояния Entity в памяти, тоже можно привязать к TransactionScope, чтобы по rollback оно делало Revert. Я не касаюсь зачем это может быть нужно, просто есть такая техническая возможность. Может запилю пример попозже, если интересно.
...
Рейтинг: 0 / 0
EF, Repository, UnitOfWork
    #38143779
Lord British
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
простейший memory-ресурс, участвовать может только в одной транзакции и контролировать только value-типы, по факту случай вырожден до тупой обработки уведомлений о commit/rollback
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;

namespace ConsoleApplication15
{
    public sealed class FakeTransactionalResource<T> : ISinglePhaseNotification
    {
        private T _oldObj;

        private T _obj;
        public T Obj
        {
            get { return _obj; }
            set { _obj = value; }
        }

        public FakeTransactionalResource(T obj)
            : this(obj, true)
        {
        }

        public FakeTransactionalResource(T obj, bool enlist)
        {
            _oldObj = obj;
            _obj = obj;

            if (enlist)
                Enlist();
        }

        public void Enlist()
        {
            Transaction.Current
                .EnlistVolatile(this, EnlistmentOptions.None);
        }

        #region ISinglePhaseNotification
        void ISinglePhaseNotification.SinglePhaseCommit(SinglePhaseEnlistment singlePhaseEnlistment)
        {
            Commit();

            singlePhaseEnlistment.Committed();
        }

        void IEnlistmentNotification.Commit(Enlistment enlistment)
        {
            throw new NotImplementedException();
        }

        void IEnlistmentNotification.InDoubt(Enlistment enlistment)
        {
            enlistment.Done();
        }

        void IEnlistmentNotification.Prepare(PreparingEnlistment preparingEnlistment)
        {
            preparingEnlistment.Prepared();
        }

        void IEnlistmentNotification.Rollback(Enlistment enlistment)
        {
            _obj = _oldObj;
        }

        private void Commit()
        {
            _oldObj = _obj;
        }

        #endregion
    }
}




пример использования
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
            FakeTransactionalResource<int> ftr = null;

            var txOptions = new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted };
            using (var tx = new TransactionScope(TransactionScopeOption.RequiresNew, txOptions))
            {
                ftr = new FakeTransactionalResource<int>(1);

                ftr.Obj = 5;

                Console.WriteLine("Before rollback {0}", ftr.Obj);
                //tx.Complete();
            }

            Console.WriteLine("After rollback {0}", ftr.Obj); // напечатает 1




может когда понадобится, используешь идею приминительно к ef, может где еще.
...
Рейтинг: 0 / 0
14 сообщений из 164, страница 7 из 7
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / EF, Repository, UnitOfWork
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]