Как вы упомянули сами, проблема в том, что future
отошел от вызова .then()
. Хитрость заключается в том, чтобы переместить его обратно, когда он будет готов. Это может быть сделано, если продолжение, переданное в .then()
, принимает future
, а не значение, которое оно содержит.
Вот функции, которые я взял из вашего кода и изменил. Я также изменил их с передачи вещей в std::async
в качестве параметров, чтобы просто захватывать их, поскольку это выглядит более интуитивно для меня, но это не является важным изменением здесь.
template <typename Work>
auto then(Work&& w) -> co_future<decltype(w())> {
return { std::async([fut = std::move(*this), w = std::forward<Work>(w)]() mutable {
fut.wait();
return w();
})};
}
template <typename Work>
auto then(Work&& w) -> co_future<decltype(w(std::move(*this)))> {
return { std::async([fut = std::move(*this), w = std::forward<Work>(w)]() mutable {
return w(std::move(fut));
})};
}
void await_suspend(std::experimental::coroutine_handle<> ch) {
then([ch, this](auto fut) mutable {
*this = std::move(fut);
ch.resume();
});
}
Кстати, VS2017 жалуется на наличие set_exception()
и unhandled_exception()
в типе обещания. Я удалил set_exception()
и изменил unhandled_exception()
на это:
void unhandled_exception() {
_promise.set_exception(std::current_exception());
}
Почему бы не сделать обычное резервное копирование (это легко сделать с помощью команды sqlcom) и добавить пользователям возможность легко восстановить это? резервный файл одним нажатием на кнопку?
Какие конечные пользователи используют вашу базу данных? Winform-программа? Затем легко сделать все с помощью нажатия кнопки для пользователя.
Вот пример кода для этого:
Declare @CustomerID int
declare @FileName nvarchar(40)
declare @ZipFileName nvarchar(40)
declare @ZipComand nvarchar(255)
set @CustomerID=20 --Get from database instead in real life application
SET @FileName='c:\backups\myback'+ cast(@customerID as nvarchar(10))+'.bak'
SET @ZipFileName='c:\backups\myback'+ cast(@customerID as nvarchar(10))+'.zip'
--Backup database northwind
backup database northwind to DISK=@FileName
--Zip the file, I got a commanddriven zip.exe from the net somewhere.
set @ZipComand= 'zip.exe -r '+@ZipFileName+' '+@FileName
EXEC xp_cmdshell @zipcomand,NO_output
--Execute the batfile that ftp:s the file to the server
exec xp_cmdshell 'c:\movetoftp.bat',no_output
--Done!
У вас должен быть файл movetoftp.bat, который содержит это (смените ftp-сервер на свой):
ftp -s: ftpcommands.txt ftp.myftp.net
И у вас должен быть файл ftpcommands.txt, содержащий это (вы можете создать этот файл динамически, используя только правильный zip-файл с помощью sqlcommands, но я позволю вам сделайте это сами):
ftpusername
ftppassword
двоичный
подскажите n
mput c: \ backups \ *. zip
выйти
Посмотрите на диалоговые окна, которые вы используете в SQL Management Studio, в верхней части каждого находится кнопка, которая будет генерировать скрипт выполнить действие. Это быстрый способ узнать, как сделать это в SQL, который можно выполнить из соединения с базой данных.
Например, чтобы отсоединить базу данных db1:
EXEC master.dbo.sp_detach_db @dbname = N'db1'
Легко - войдите в SMO «Объекты управления SQL», которые поставляются с SQL Server - классы C # / VB.NET и способы сделать все это.
См .: SMO - управлять своим SQL Server!
или:
Резервное копирование и восстановление базы данных SQL Server 2005 с использованием C # и .NET 2.0
Marc
Лично я буду создавать резервные копии базы данных, архивировать их и отправлять пользователям. Возможно, вы могли бы написать небольшой скрипт для восстановления.
Причина отключения базы данных делает ее недоступной для других.
Я бы использовал консольную версию SQL Dumper и сжал дамп sql.
IMHO всегда лучше иметь текстовую копию вместо двоичного файла. Если что-то идет не так, по крайней мере, вы можете переписать свои данные вручную, потому что вы можете прочитать их.