lmoelleb
Почему это проблема, чтобы сделать его потокобезопасным? Обычно вызов обрабатывается одним потоком (старый способ) или одной асинхронной "цепочкой" вызовов, которая также защитит ваш код от проблем с потоками - если только вы не запускаете потоки самостоятельно.
Но поскольку вы хотите сгенерировать файл, я не вижу, где происходит загрузка?
На уровне данных хранятся только данные и осуществляется доступ к ним. Он не будет иметь функциональности для создания файлов и т. д. Так что это будет означать, что бизнес-слой должен будет это сделать
В среде с высокими требованиями к масштабированию создание файла счета-фактуры, вероятно, будет выполняться фоновым работником, выполняющим очередь. В небольших системах вам может сойти с рук его генерация по мере того, как данные вставляются в базу данных. Если вам нужно задать этот вопрос, вы не должны работать над крупномасштабной системой, прежде чем получите немного больше опыта.
Для большинства небольших систем Вам может сойти с рук один из этих подходов:
Генерируйте файл по мере того, как данные хранятся в системе.
1) начать объем транзакции
2) вставьте данные для счета-фактуры
3) создайте файл счета-фактуры (и сохраните его также - база данных? файловая система, хранилище blob-объектов, …)
4) совершить транзакцию. Таким образом, вы получите откат, и данные счета-фактуры не будут сохранены, даже если хранение файла на диске завершится неудачей, если вам действительно не повезет (а вам может действительно не повезти и с транзакциями, так что не беспокойтесь об этом)
Или альтернативно вы можете сгенерировать файл при чтении (если это приемлемо, то это скорее бизнес-вопрос, чем вопрос программирования). Таким образом, он не хранится в самой базе данных и обычно кэшируется в файловой системе только на короткое время - если вообще кэшируется.
1) Запустите транзакцию базы данных
2) хранить данные счета-фактуры
3) совершить транзакцию
Когда придет запрос API, сгенерируйте файл и верните его. Если производительность показывает проблему и вы часто получаете несколько запросов на один и тот же файл, то кэшируйте сгенерированные файлы на диске. Просто помните, что вы все равно должны проверить безопасность - не просто возвращайте файл первому лучшему абоненту, знающему номер счета (люди будет попробуйте добавить или вычесть номер счета-фактуры оттуда собственный URL-адрес получения счета-фактуры).
Navneet Kumar
Спасибо за подробное решение. Я хочу понять, где поместить мой код сохранения файла, на уровне данных или бизнес-уровне, потому что не рекомендуется использовать область транзакций на бизнес-уровне.
lmoelleb
In a lot of cases it is not advisable to use a transaction scope anywhere :). Where the correct level is for your application is impossible to say - you do not have the experience to determine it, we do not have enough insight into your application to determine it. So the best approach is to implement it in the least complicated way, then be ready to change it if needed. The last option I give (generate invoices on read) or the comment I made about high scale systems using a background queue both could satisfy the requirement of not needing transactions in the business layer. Saving the invoice data can be handled by a single transaction in the data layer. Generating an invoice in the data layer in order to avoid transactions in the business logic is not an option, as you would just move business logic into your data layer - meaning you would still have transactions in your business logic AND you would have business logic code in your data layer code. Worst of both worlds.