public async Task <int> WriteWithTransactionUsingDmlCoreAsync(string projectId, string instanceId, string databaseId) { // This sample transfers 200,000 from the MarketingBudget // field of the second Album to the first Album. Make sure to run // the AddColumnAsyncSample and WriteDataToNewColumnAsyncSample first, // in that order. string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}"; decimal transferAmount = 200000; decimal secondBudget = 0; // Create connection to Cloud Spanner. using var connection = new SpannerConnection(connectionString); await connection.OpenAsync(); // Create a readwrite transaction that we'll assign // to each SpannerCommand. using var transaction = await connection.BeginTransactionAsync(); // Create statement to select the second album's data. var cmdLookup = connection.CreateSelectCommand("SELECT * FROM Albums WHERE SingerId = 2 AND AlbumId = 2"); cmdLookup.Transaction = transaction; // Execute the select query. using var reader1 = await cmdLookup.ExecuteReaderAsync(); while (await reader1.ReadAsync()) { // Read the second album's budget. secondBudget = reader1.GetFieldValue <decimal>("MarketingBudget"); // Confirm second Album's budget is sufficient and // if not raise an exception. Raising an exception // will automatically roll back the transaction. if (secondBudget < transferAmount) { throw new Exception($"The second album's budget {secondBudget} is less than the amount to transfer."); } } // Update second album to remove the transfer amount. secondBudget -= transferAmount; SpannerCommand cmd = connection.CreateDmlCommand("UPDATE Albums SET MarketingBudget = @MarketingBudget WHERE SingerId = 2 and AlbumId = 2"); cmd.Parameters.Add("MarketingBudget", SpannerDbType.Int64, secondBudget); cmd.Transaction = transaction; var rowCount = await cmd.ExecuteNonQueryAsync(); // Update first album to add the transfer amount. cmd = connection.CreateDmlCommand("UPDATE Albums SET MarketingBudget = MarketingBudget + @MarketingBudgetIncrement WHERE SingerId = 1 and AlbumId = 1"); cmd.Parameters.Add("MarketingBudgetIncrement", SpannerDbType.Int64, transferAmount); cmd.Transaction = transaction; rowCount += await cmd.ExecuteNonQueryAsync(); await transaction.CommitAsync(); Console.WriteLine("Transaction complete."); return(rowCount); }
public async Task <int> DeleteDataAsync(string projectId, string instanceId, string databaseId) { string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}"; var albums = new List <Album> { new Album { SingerId = 2, AlbumId = 1, AlbumTitle = "Green" }, new Album { SingerId = 2, AlbumId = 3, AlbumTitle = "Terrified" }, }; int rowCount = 0; using (var connection = new SpannerConnection(connectionString)) { await connection.OpenAsync(); // Delete individual rows from the Albums table. await Task.WhenAll(albums.Select(async album => { var cmd = connection.CreateDeleteCommand("Albums", new SpannerParameterCollection { { "SingerId", SpannerDbType.Int64, album.SingerId }, { "AlbumId", SpannerDbType.Int64, album.AlbumId } }); rowCount += await cmd.ExecuteNonQueryAsync(); })); Console.WriteLine("Deleted individual rows in Albums."); // Delete a range of rows from the Singers table where the column key is >=3 and <5. var cmd = connection.CreateDmlCommand("DELETE FROM Singers WHERE SingerId >= 3 AND SingerId < 5"); rowCount += await cmd.ExecuteNonQueryAsync(); Console.WriteLine($"{rowCount} row(s) deleted from Singers."); // Delete remaining Singers rows, which will also delete the remaining // Albums rows since it was defined with ON DELETE CASCADE. cmd = connection.CreateDmlCommand("DELETE FROM Singers WHERE true"); rowCount += await cmd.ExecuteNonQueryAsync(); Console.WriteLine($"{rowCount} row(s) deleted from Singers."); } return(rowCount); }
public async Task <long> LogCommitStatsAsync(string projectId, string instanceId, string databaseId) { // Commit statistics are logged at level Info by the default logger. // This sample uses a custom logger to access the commit statistics. // See https://googleapis.github.io/google-cloud-dotnet/docs/Google.Cloud.Spanner.Data/logging.html // for more information on how to use loggers. var logger = new CommitStatsSampleLogger(); var options = new SessionPoolOptions(); var poolManager = SessionPoolManager.Create(options, logger); var connectionStringBuilder = new SpannerConnectionStringBuilder { ConnectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}", // Set LogCommitStats to true to enable logging commit statistics for all transactions on the connection. // LogCommitStats can also be enabled/disabled for individual Spanner transactions. LogCommitStats = true, SessionPoolManager = poolManager, }; using var connection = new SpannerConnection(connectionStringBuilder); await connection.OpenAsync(); using var cmd = connection.CreateDmlCommand("INSERT Singers (SingerId, FirstName, LastName) VALUES (110, 'Virginia', 'Watson')"); var rowCount = await cmd.ExecuteNonQueryAsync(); var mutationCount = logger._lastCommitResponse.CommitStats.MutationCount; Console.WriteLine($"{rowCount} row(s) inserted..."); Console.WriteLine($"{mutationCount} mutation(s) in transaction..."); return(mutationCount); }
public void EphemeralTransactionIncludesPriorityOnDmlCommandAndCommit() { var priority = Priority.Medium; Mock <SpannerClient> spannerClientMock = SpannerClientHelpers .CreateMockClient(Logger.DefaultLogger, MockBehavior.Strict); spannerClientMock .SetupBatchCreateSessionsAsync() .SetupBeginTransactionAsync() .SetupExecuteStreamingSqlForDml(ResultSetStats.RowCountOneofCase.RowCountExact) .SetupCommitAsync(); SpannerConnection connection = BuildSpannerConnection(spannerClientMock); var command = connection.CreateDmlCommand("UPDATE FOO SET BAR=1 WHERE ID=1"); command.Priority = priority; command.ExecuteNonQuery(); spannerClientMock.Verify(client => client.ExecuteStreamingSql( It.Is <ExecuteSqlRequest>(request => request.RequestOptions.Priority == PriorityConverter.ToProto(priority)), It.IsAny <CallSettings>()), Times.Once()); spannerClientMock.Verify(client => client.CommitAsync( It.Is <CommitRequest>(request => request.RequestOptions.Priority == PriorityConverter.ToProto(priority)), It.IsAny <CallSettings>()), Times.Once()); }
private async Task <int> DmlUpdateFixtureData(string key, SpannerConnection connection, SpannerTransaction transaction) { using (var command = connection.CreateDmlCommand(_updateSql)) { command.Transaction = transaction; command.Parameters.Add("Key", SpannerDbType.String, key); return(await command.ExecuteNonQueryAsync()); } }
public async Task <bool> AddGameInfo(string name, string author, string path) { using (var connection = new SpannerConnection(CONNECTION_STRING)) { var cmd = connection.CreateDmlCommand( $@"INSERT INTO game (name, author, path) VALUES ('{name}', '{author}', '{path}')"); int rowCount = await cmd.ExecuteNonQueryAsync(); return(rowCount == 1); } }
public async Task <int> InsertUsingDmlCoreAsync(string projectId, string instanceId, string databaseId) { string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}"; using var connection = new SpannerConnection(connectionString); await connection.OpenAsync(); using var cmd = connection.CreateDmlCommand("INSERT Singers (SingerId, FirstName, LastName) VALUES (10, 'Virginia', 'Watson')"); int rowCount = await cmd.ExecuteNonQueryAsync(); Console.WriteLine($"{rowCount} row(s) inserted..."); return(rowCount); }
public async Task <int> UpdateUsingDmlWithTimestampCoreAsync(string projectId, string instanceId, string databaseId) { string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}"; using var connection = new SpannerConnection(connectionString); await connection.OpenAsync(); using var cmd = connection.CreateDmlCommand("UPDATE Albums SET LastUpdateTime = PENDING_COMMIT_TIMESTAMP() WHERE SingerId = 1"); int rowCount = await cmd.ExecuteNonQueryAsync(); Console.WriteLine($"{rowCount} row(s) updated..."); return(rowCount); }
public async Task <int> DeleteUsingDmlCoreAsync(string projectId, string instanceId, string databaseId) { string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}"; using var connection = new SpannerConnection(connectionString); await connection.OpenAsync(); using var cmd = connection.CreateDmlCommand("DELETE FROM Singers WHERE FirstName = 'Alice'"); int rowCount = await cmd.ExecuteNonQueryAsync(); Console.WriteLine($"{rowCount} row(s) deleted..."); return(rowCount); }
public async Task <int> UpdateUsingDmlCoreAsync(string projectId, string instanceId, string databaseId) { string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}"; using var connection = new SpannerConnection(connectionString); await connection.OpenAsync(); using var cmd = connection.CreateDmlCommand("UPDATE Albums SET MarketingBudget = MarketingBudget * 2 WHERE SingerId = 1 and AlbumId = 1"); int rowCount = await cmd.ExecuteNonQueryAsync(); Console.WriteLine($"{rowCount} row(s) updated..."); return(rowCount); }
public async Task <long> DeleteUsingPartitionedDmlCoreAsync(string projectId, string instanceId, string databaseId) { string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}"; using var connection = new SpannerConnection(connectionString); await connection.OpenAsync(); using var cmd = connection.CreateDmlCommand("DELETE FROM Singers WHERE SingerId > 10"); long rowCount = await cmd.ExecutePartitionedUpdateAsync(); Console.WriteLine($"{rowCount} row(s) deleted..."); return(rowCount); }
public async Task <int> TransactionTagAsync(string projectId, string instanceId, string databaseId) { string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}"; using var connection = new SpannerConnection(connectionString); await connection.OpenAsync(); return(await connection.RunWithRetriableTransactionAsync(async transaction => { // Sets the transaction tag to "app=concert,env=dev". // This transaction tag will be applied to all the individual operations inside // the transaction. transaction.Tag = "app=concert,env=dev"; // Sets the request tag to "app=concert,env=dev,action=update". // This request tag will only be set on this request. var updateCommand = connection.CreateDmlCommand("UPDATE Venues SET Capacity = DIV(Capacity, 4) WHERE OutdoorVenue = false"); updateCommand.Tag = "app=concert,env=dev,action=update"; await updateCommand.ExecuteNonQueryAsync(); var insertCommand = connection.CreateDmlCommand( @"INSERT INTO Venues (VenueId, VenueName, Capacity, OutdoorVenue, LastUpdateTime) VALUES (@venueId, @venueName, @capacity, @outdoorVenue, PENDING_COMMIT_TIMESTAMP())", new SpannerParameterCollection { { "venueId", SpannerDbType.Int64, 81 }, { "venueName", SpannerDbType.String, "Venue 81" }, { "capacity", SpannerDbType.Int64, 1440 }, { "outdoorVenue", SpannerDbType.Bool, true } } ); // Sets the request tag to "app=concert,env=dev,action=insert". // This request tag will only be set on this request. insertCommand.Tag = "app=concert,env=dev,action=insert"; return await insertCommand.ExecuteNonQueryAsync(); })); }
public async Task <int> UpdateDataAsync(string projectId, string instanceId, string databaseId) { string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}"; using var connection = new SpannerConnection(connectionString); var rowCount = 0; SpannerCommand cmd = connection.CreateDmlCommand( "UPDATE Albums SET MarketingBudget = @MarketingBudget " + "WHERE SingerId = 1 and AlbumId = 1"); cmd.Parameters.Add("MarketingBudget", SpannerDbType.Int64, 100000); rowCount += await cmd.ExecuteNonQueryAsync(); cmd = connection.CreateDmlCommand( "UPDATE Albums SET MarketingBudget = @MarketingBudget " + "WHERE SingerId = 2 and AlbumId = 2"); cmd.Parameters.Add("MarketingBudget", SpannerDbType.Int64, 500000); rowCount += await cmd.ExecuteNonQueryAsync(); Console.WriteLine("Data Updated."); return(rowCount); }
public async Task SetActualRates(ICollection <CurrencyRate> rates) { await using var connection = new SpannerConnection(connectionString); await connection.OpenAsync(); var actualRates = await GetRatesImpl(connection); var tasks = new List <Task>(); foreach (var newRate in rates) { var actualRate = actualRates.FirstOrDefault(r => r.Key == newRate.Key); if (actualRate == null) { var insertActualRate = connection.CreateInsertCommand("actual_rates"); insertActualRate.Parameters.Add("currency_from", SpannerDbType.String, newRate.CurrencyFrom); insertActualRate.Parameters.Add("currency_to", SpannerDbType.String, newRate.CurrencyTo); insertActualRate.Parameters.Add("provider_name", SpannerDbType.String, newRate.ProviderName); insertActualRate.Parameters.Add("expiration_time", SpannerDbType.Timestamp, newRate.ExpirationTime); insertActualRate.Parameters.Add("original_published_time", SpannerDbType.Timestamp, newRate.OriginalPublishedTime); insertActualRate.Parameters.Add("time_of_receipt", SpannerDbType.Timestamp, newRate.TimeOfReceipt); insertActualRate.Parameters.Add("value", SpannerDbType.Int64, newRate.Value); tasks.Add(insertActualRate.ExecuteNonQueryAsync()); } else { actualRate.Update(newRate, mapper); var cmd = connection.CreateDmlCommand( "UPDATE actual_rates " + "SET expiration_time = @expiration_time, " + "original_published_time = @original_published_time, " + "provider_name = @provider_name, " + "time_of_receipt = @time_of_receipt, " + "value = @value " + "WHERE currency_from = @currency_from and currency_to = @currency_to"); cmd.Parameters.Add("provider_name", SpannerDbType.String, newRate.ProviderName); cmd.Parameters.Add("expiration_time", SpannerDbType.Timestamp, newRate.ExpirationTime); cmd.Parameters.Add("original_published_time", SpannerDbType.Timestamp, newRate.OriginalPublishedTime); cmd.Parameters.Add("time_of_receipt", SpannerDbType.Timestamp, newRate.TimeOfReceipt); cmd.Parameters.Add("value", SpannerDbType.Int64, newRate.Value); tasks.Add(cmd.ExecuteNonQueryAsync()); } } await Task.WhenAll(tasks); }
public static async Task InsertPlayersAsync(string projectId, string instanceId, string databaseId) { string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}" + $"/databases/{databaseId}"; long numberOfPlayers = 0; using (var connection = new SpannerConnection(connectionString)) { await connection.OpenAsync(); await connection.RunWithRetriableTransactionAsync(async (transaction) => { // Execute a SQL statement to get current number of records // in the Players table to use as an incrementing value // for each PlayerName to be inserted. var cmd = connection.CreateSelectCommand( @"SELECT Count(PlayerId) as PlayerCount FROM Players"); numberOfPlayers = await cmd.ExecuteScalarAsync <long>(); // Insert 100 player records into the Players table. SpannerBatchCommand cmdBatch = connection.CreateBatchDmlCommand(); for (int i = 0; i < 100; i++) { numberOfPlayers++; SpannerCommand cmdInsert = connection.CreateDmlCommand( "INSERT INTO Players " + "(PlayerId, PlayerName) " + "VALUES (@PlayerId, @PlayerName)", new SpannerParameterCollection { { "PlayerId", SpannerDbType.Int64 }, { "PlayerName", SpannerDbType.String } }); cmdInsert.Parameters["PlayerId"].Value = Math.Abs(Guid.NewGuid().GetHashCode()); cmdInsert.Parameters["PlayerName"].Value = $"Player {numberOfPlayers}"; cmdBatch.Add(cmdInsert); } await cmdBatch.ExecuteNonQueryAsync(); }); } Console.WriteLine("Done inserting player records..."); }
public async Task <int> WriteUsingDmlCoreAsync(string projectId, string instanceId, string databaseId) { string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}"; using var connection = new SpannerConnection(connectionString); await connection.OpenAsync(); SpannerCommand cmd = connection.CreateDmlCommand( "INSERT Singers (SingerId, FirstName, LastName) VALUES " + "(12, 'Melissa', 'Garcia'), " + "(13, 'Russell', 'Morales'), " + "(14, 'Jacqueline', 'Long'), " + "(15, 'Dylan', 'Shaw')"); int rowCount = await cmd.ExecuteNonQueryAsync(); Console.WriteLine($"{rowCount} row(s) inserted..."); return(rowCount); }
public void PdmlRetriedOnEosError() { Mock<SpannerClient> spannerClientMock = SpannerClientHelpers .CreateMockClient(Logger.DefaultLogger, MockBehavior.Strict); spannerClientMock .SetupBatchCreateSessionsAsync() .SetupBeginTransactionAsync() .SetupExecuteStreamingSqlForDmlThrowingEosError(); SpannerConnection connection = BuildSpannerConnection(spannerClientMock); var command = connection.CreateDmlCommand("UPDATE abc SET xyz = 1 WHERE Id > 1"); long rowCount = command.ExecutePartitionedUpdate(); Assert.True(rowCount > 0); spannerClientMock.Verify(client => client.ExecuteStreamingSql( It.IsAny<ExecuteSqlRequest>(), It.IsAny<CallSettings>()), Times.Exactly(3)); }
public async Task <int> UpdateUsingDmlWithStructCoreAsync(string projectId, string instanceId, string databaseId) { var nameStruct = new SpannerStruct { { "FirstName", SpannerDbType.String, "Timothy" }, { "LastName", SpannerDbType.String, "Campbell" } }; string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}"; using var connection = new SpannerConnection(connectionString); await connection.OpenAsync(); using var cmd = connection.CreateDmlCommand("UPDATE Singers SET LastName = 'Grant' WHERE STRUCT<FirstName STRING, LastName STRING>(FirstName, LastName) = @name"); cmd.Parameters.Add("name", nameStruct.GetSpannerDbType(), nameStruct); int rowCount = await cmd.ExecuteNonQueryAsync(); Console.WriteLine($"{rowCount} row(s) updated..."); return(rowCount); }
public void PdmlCommandIncludesPriority() { Mock <SpannerClient> spannerClientMock = SpannerClientHelpers .CreateMockClient(Logger.DefaultLogger, MockBehavior.Strict); spannerClientMock .SetupBatchCreateSessionsAsync() .SetupBeginTransactionAsync() .SetupExecuteStreamingSqlForDml(ResultSetStats.RowCountOneofCase.RowCountLowerBound); SpannerConnection connection = BuildSpannerConnection(spannerClientMock); var command = connection.CreateDmlCommand("DELETE FROM Users WHERE Active=False"); command.Priority = Priority.Low; command.ExecutePartitionedUpdate(); spannerClientMock.Verify(client => client.ExecuteStreamingSql( It.Is <ExecuteSqlRequest>(request => request.RequestOptions.Priority == RequestOptions.Types.Priority.Low), It.IsAny <CallSettings>()), Times.Once()); }
public async Task <int> WriteAndReadUsingDmlCoreAsync(string projectId, string instanceId, string databaseId) { string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}"; using var connection = new SpannerConnection(connectionString); await connection.OpenAsync(); using var createDmlCmd = connection.CreateDmlCommand(@"INSERT Singers (SingerId, FirstName, LastName) VALUES (11, 'Timothy', 'Campbell')"); int rowCount = await createDmlCmd.ExecuteNonQueryAsync(); Console.WriteLine($"{rowCount} row(s) inserted..."); // Read newly inserted record. using var createSelectCmd = connection.CreateSelectCommand(@"SELECT FirstName, LastName FROM Singers WHERE SingerId = 11"); using var reader = await createSelectCmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { Console.WriteLine($"{reader.GetFieldValue<string>("FirstName")} {reader.GetFieldValue<string>("LastName")}"); } return(rowCount); }
public static async Task InsertScoresAsync( string projectId, string instanceId, string databaseId) { string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}" + $"/databases/{databaseId}"; // Insert 4 score records into the Scores table for each player // in the Players table. using (var connection = new SpannerConnection(connectionString)) { await connection.OpenAsync(); await connection.RunWithRetriableTransactionAsync(async (transaction) => { Random r = new Random(); bool playerRecordsFound = false; SpannerBatchCommand cmdBatch = connection.CreateBatchDmlCommand(); var cmdLookup = connection.CreateSelectCommand("SELECT * FROM Players"); using (var reader = await cmdLookup.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { playerRecordsFound = true; for (int i = 0; i < 4; i++) { DateTime randomTimestamp = DateTime.Now .AddYears(r.Next(-2, 1)) .AddMonths(r.Next(-12, 1)) .AddDays(r.Next(-10, 1)) .AddSeconds(r.Next(-60, 0)) .AddMilliseconds(r.Next(-100000, 0)); SpannerCommand cmdInsert = connection.CreateDmlCommand( "INSERT INTO Scores " + "(PlayerId, Score, Timestamp) " + "VALUES (@PlayerId, @Score, @Timestamp)", new SpannerParameterCollection { { "PlayerId", SpannerDbType.Int64 }, { "Score", SpannerDbType.Int64 }, { "Timestamp", SpannerDbType.Timestamp } }); cmdInsert.Parameters["PlayerId"].Value = reader.GetFieldValue <int>("PlayerId"); cmdInsert.Parameters["Score"].Value = r.Next(1000, 1000001); cmdInsert.Parameters["Timestamp"].Value = randomTimestamp.ToString("o"); cmdBatch.Add(cmdInsert); } } if (!playerRecordsFound) { Console.WriteLine("Parameter 'scores' is invalid " + "since no player records currently exist. First " + "insert players then insert scores."); Environment.Exit((int)ExitCode.InvalidParameter); } else { await cmdBatch.ExecuteNonQueryAsync(); Console.WriteLine( "Done inserting score records..." ); } } }); } }
public static async Task InsertPlayersAsync(string projectId, string instanceId, string databaseId) { string connectionString = $"Data Source=projects/{projectId}/instances/{instanceId}" + $"/databases/{databaseId}"; using (TransactionScope scope = new TransactionScope( TransactionScopeAsyncFlowOption.Enabled)) { Int64 numberOfPlayers = 0; using (var connection = new SpannerConnection(connectionString)) { await connection.OpenAsync(); // Execute a SQL statement to get current number of records // in the Players table to use as an incrementing value // for each PlayerName to be inserted. var cmd = connection.CreateSelectCommand( @"SELECT Count(PlayerId) as PlayerCount FROM Players"); using (var reader = await cmd.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { long parsedValue; if (reader["PlayerCount"] != DBNull.Value) { bool result = Int64.TryParse( reader.GetFieldValue <string>("PlayerCount"), out parsedValue); if (result) { numberOfPlayers = parsedValue; } } } } // Insert 100 player records into the Players table. SpannerBatchCommand cmdBatch = connection.CreateBatchDmlCommand(); for (var x = 1; x <= 100; x++) { numberOfPlayers++; SpannerCommand cmdInsert = connection.CreateDmlCommand( "INSERT INTO Players " + "(PlayerId, PlayerName) " + "VALUES (@PlayerId, @PlayerName)", new SpannerParameterCollection { { "PlayerId", SpannerDbType.Int64 }, { "PlayerName", SpannerDbType.String } }); cmdInsert.Parameters["PlayerId"].Value = Math.Abs(Guid.NewGuid().GetHashCode()); cmdInsert.Parameters["PlayerName"].Value = $"Player {numberOfPlayers}"; cmdBatch.Add(cmdInsert); } await cmdBatch.ExecuteNonQueryAsync(); scope.Complete(); } } Console.WriteLine("Done inserting player records..."); }