private async Task ExecuteAsync(Database database) { using (var connection = GetConnection()) using (var command = connection.CreateCommand()) { var virtualDeviceName = $"sqlsnap-{Guid.NewGuid()}"; command.CommandText = GetSqlCommand(virtualDeviceName, database.Name); command.CommandTimeout = _timeout; var config = new VDConfig { DeviceCount = 1, Features = VDFeature.SnapshotPrepare }; Log.Debug("Creating virtual device {virtualDeviceName}", virtualDeviceName); var virtualDeviceSet = (IClientVirtualDeviceSet2) new ClientVirtualDeviceSet2(); virtualDeviceSet.CreateEx(_instanceName, virtualDeviceName, ref config); try { Log.Debug("Executing SQL query: {commandText}", command.CommandText); var queryTask = command.ExecuteNonQueryAsync(); await Task.Run(() => { Log.Debug("Waiting for virtual device to be ready"); var virtualDevice = WaitForDevice(virtualDeviceSet, virtualDeviceName); Log.Debug("Receiving commands from virtual device"); HandleCommands(database, virtualDevice); }); Log.Debug("Waiting for query to finish"); await queryTask; } finally { try { virtualDeviceSet.Close(); } catch { // ignore errors when closing } } } }
private IClientVirtualDevice WaitForDevice(IClientVirtualDeviceSet2 virtualDeviceSet, string virtualDeviceName) { var config = new VDConfig(); while (true) { try { virtualDeviceSet.GetConfiguration(1000, ref config); break; } catch (COMException ex) { if ((uint)ex.ErrorCode == 0x80770003) // timeout { continue; } throw; } } return(virtualDeviceSet.OpenDevice(virtualDeviceName)); }