Class DatastoreTransaction (4.2.0)

public abstract class DatastoreTransaction : IDisposable

Convenience wrapper around a Datastore transaction. All mutation operations (Insert(IEnumerable<Entity>), Delete(IEnumerable<Key>), Update(IEnumerable<Entity>) and Upsert(IEnumerable<Entity>)) merely add to a list of mutations which are performed in a single Commit(CallSettings) or CommitAsync(CallSettings) operation. This means the mutation methods are all synchronous and do not take call settings, as they don't perform any API operations.

Datastore limits the number of entities that can be modified in a Commit operation, and therefore one transaction. When modifying a large number of entities, partition the changes into multiple transactions. See Datastore limits for more details on Datastore limits.

Even though transactions aren't inherently related to a specific partition ID, the expected usage is that queries run inside a transaction are likely to be in a single partition, specified in a DatastoreDb used to create the transaction.

Disposing of a transaction calls Rollback(CallSettings) if the transaction has not already been committed or rolled back.

This is an abstract class, implemented by DatastoreTransactionImpl for production use. Users creating their own DatastoreDb subclasses may choose to create fake implementations for testing purposes. There are no abstract methods in this class; instead, all methods either delegate to another or throw NotImplementedException.

Inheritance

Object > DatastoreTransaction

Implements

IDisposable

Derived Types

Namespace

Google.Cloud.Datastore.V1

Assembly

Google.Cloud.Datastore.V1.dll

Properties

TransactionId

public virtual ByteString TransactionId { get; }

The ID of the transaction, used implicitly in operations performed with this object.

Property Value
TypeDescription
ByteString

Methods

Commit(CallSettings)

public virtual CommitResponse Commit(CallSettings callSettings = null)

Commits all mutations in this transaction.

Parameter
NameDescription
callSettingsCallSettings
Returns
TypeDescription
CommitResponse

The response from the commit operation. This can be used to determine server-allocated keys.

Remarks

Any entities with incomplete keys that are assigned keys by this operation will be updated in memory with the server-allocated keys.

Datastore limits the number of entities that can be modified in a Commit operation, and therefore one transaction. When modifying a large number of entities, partition the changes into multiple transactions. See Datastore limits for more details on Datastore limits.

Example
DatastoreDb db = DatastoreDb.Create(projectId, namespaceId);
KeyFactory keyFactory = db.CreateKeyFactory("message");
using (DatastoreTransaction transaction = db.BeginTransaction())
{
    Entity entity = new Entity
    {
        Key = keyFactory.CreateIncompleteKey(),
        ["message"] = "Hello"
    };
    // This adds the entity to a collection in memory: nothing
    // is sent to the server.
    transaction.Insert(entity);
    // Without the Commit call, the transaction will automatically
    // be rolled back. The Commit call performs all the mutations
    // within the transaction.
    transaction.Commit();
}
Exceptions
TypeDescription
InvalidOperationException

The transaction has already been committed or rolled back.

CommitAsync(CallSettings)

public virtual Task<CommitResponse> CommitAsync(CallSettings callSettings = null)

Commits all mutations in this transaction asynchronously.

Parameter
NameDescription
callSettingsCallSettings

If not null, applies overrides to RPC calls.

Returns
TypeDescription
Task<CommitResponse>

The response from the commit operation. This can be used to determine server-allocated keys.

Remarks

Any entities with incomplete keys that are assigned keys by this operation will be updated in memory with the server-allocated keys.

Datastore limits the number of entities that can be modified in a Commit operation, and therefore one transaction. When modifying a large number of entities, partition the changes into multiple transactions. See Datastore limits for more details on Datastore limits.

Example

See Commit for a synchronous example.

Exceptions
TypeDescription
InvalidOperationException

The transaction has already been committed or rolled back.

Create(DatastoreClient, String, String, ByteString)

public static DatastoreTransaction Create(DatastoreClient client, string projectId, string namespaceId, ByteString transactionId)

Constructs an instance of DatastoreClientImpl with the given arguments. Clients using the DatastoreDb abstraction layer would normally call BeginTransaction(CallSettings) or BeginTransactionAsync(CallSettings) instead of calling this method directly.

Parameters
NameDescription
clientDatastoreClient

The client to use for Datastore operations. Must not be null.

projectIdString

The ID of the project of the Datastore operations. Must not be null.

namespaceIdString

The ID of the namespace which is combined with projectId to form a partition ID to use in query operations. May be null.

transactionIdByteString

The transaction obtained by an earlier BeginTransaction(String, CallSettings) or the asynchronous equivalent. Must not be null

Returns
TypeDescription
DatastoreTransaction

A DatastoreTransaction representation of the specified transaction.

Delete(Entity[])

public virtual void Delete(params Entity[] entities)

Adds delete operations for all the specified keys to this transaction.

Parameter
NameDescription
entitiesEntity[]

The entities to delete. Must not be null.

Remarks

This method delegates to Delete(IEnumerable<Entity>).

Example
DatastoreDb db = DatastoreDb.Create(projectId, namespaceId);
KeyFactory keyFactory = db.CreateKeyFactory("message");
Entity message = new Entity
{
    Key = keyFactory.CreateIncompleteKey(),
    ["text"] = "Hello",
};
db.Insert(message);

Entity fetchedBeforeDeletion = db.Lookup(message.Key);

using (DatastoreTransaction transaction = db.BeginTransaction())
{
    // This adds the entity key to a collection of mutations in memory: nothing
    // is sent to the server. Only the key from the entity is used to determine what to delete.
    // If you already have the key but not the entity, use Delete(Key[]) or
    // a similar overload.
    transaction.Delete(message);
    // Without the Commit call, the transaction will automatically
    // be rolled back. The Commit call performs all the mutations
    // within the transaction.
    transaction.Commit();
}

Entity fetchedAfterDeletion = db.Lookup(message.Key);

Console.WriteLine($"Entity exists before deletion? {fetchedBeforeDeletion != null}");
Console.WriteLine($"Entity exists after deletion? {fetchedAfterDeletion != null}");

Delete(Key[])

public virtual void Delete(params Key[] keys)

Adds deletion operations for all the specified keys to this transaction.

Parameter
NameDescription
keysKey[]

The keys to delete. Must not be null.

Remarks

This method delegates to Delete(IEnumerable<Key>).

Example
DatastoreDb db = DatastoreDb.Create(projectId, namespaceId);
KeyFactory keyFactory = db.CreateKeyFactory("message");
Entity message = new Entity
{
    Key = keyFactory.CreateIncompleteKey(),
    ["text"] = "Hello",
};
Key key = db.Insert(message);

Entity fetchedBeforeDeletion = db.Lookup(key);

using (DatastoreTransaction transaction = db.BeginTransaction())
{
    // This adds the key to a collection of mutations in memory: nothing
    // is sent to the server. Only the key is required to determine what to delete.
    // If you have an entity with the right key, you can use Delete(Entity[])
    // or a similar overload for convenience.
    transaction.Delete(key);
    // Without the Commit call, the transaction will automatically
    // be rolled back. The Commit call performs all the mutations
    // within the transaction.
    transaction.Commit();
}

Entity fetchedAfterDeletion = db.Lookup(key);

Console.WriteLine($"Entity exists before deletion? {fetchedBeforeDeletion != null}");
Console.WriteLine($"Entity exists after deletion? {fetchedAfterDeletion != null}");

Delete(IEnumerable<Entity>)

public virtual void Delete(IEnumerable<Entity> entities)

Adds delete operations for all the specified keys to this transaction.

Parameter
NameDescription
entitiesIEnumerable<Entity>

The entities to delete. Must not be null.

Example

See Delete for an example using an alternative overload.

Delete(IEnumerable<Key>)

public virtual void Delete(IEnumerable<Key> keys)

Adds deletion operations for all the specified keys to this transaction.

Parameter
NameDescription
keysIEnumerable<Key>

The keys to delete. Must not be null.

Example

See Delete for an example using an alternative overload.

Dispose()

public virtual void Dispose()

If the transaction has already been committed, this operation is a no-op. Otherwise, it rolls back the transaction.

Insert(Entity[])

public virtual void Insert(params Entity[] entities)

Adds insert operations for all the specified keys to this transaction.

Parameter
NameDescription
entitiesEntity[]

The entities to insert. Must not be null.

Remarks

This method delegates to Insert(IEnumerable<Entity>).

Example
DatastoreDb db = DatastoreDb.Create(projectId, namespaceId);
KeyFactory keyFactory = db.CreateKeyFactory("message");
using (DatastoreTransaction transaction = db.BeginTransaction())
{
    Entity entity = new Entity
    {
        Key = keyFactory.CreateIncompleteKey(),
        ["message"] = "Hello"
    };
    // This adds the entity to a collection in memory: nothing
    // is sent to the server.
    transaction.Insert(entity);
    // Without the Commit call, the transaction will automatically
    // be rolled back. The Commit call performs all the mutations
    // within the transaction.
    transaction.Commit();
}

Insert(IEnumerable<Entity>)

public virtual void Insert(IEnumerable<Entity> entities)

Adds insert operations for all the specified keys to this transaction.

Parameter
NameDescription
entitiesIEnumerable<Entity>

The entities to insert. Must not be null.

Example

See Insert for an example using an alternative overload.

Lookup(Key, CallSettings)

public virtual Entity Lookup(Key key, CallSettings callSettings = null)

Looks up a single entity by key.

Parameters
NameDescription
keyKey

The key to look up. Must not be null, and must be complete.

callSettingsCallSettings

If not null, applies overrides to this RPC call.

Returns
TypeDescription
Entity

The entity with the specified key, or null if no such entity exists.

Remarks

This method simply delegates to Lookup(IEnumerable<Key>, CallSettings).

Example

See Lookup for an example using an alternative overload.

Lookup(Key[])

public virtual IReadOnlyList<Entity> Lookup(params Key[] keys)

Looks up a collection of entities by key.

Parameter
NameDescription
keysKey[]

The keys to look up. Must not be null, and every element must be non-null and refer to a complete key.

Returns
TypeDescription
IReadOnlyList<Entity>

A collection of entities with the same size as keys, containing corresponding entity references, or null where the key was not found.

Remarks

This call may perform multiple RPC operations in order to look up all keys.

This overload does not support the CallSettings to be specified due to restrictions with methods containing a parameter array and optional parameters. It simply delegates to Lookup(IEnumerable<Key>, CallSettings), passing in a null value for the call settings.

Datastore limits the number of entities that can be looked up in a single operation. When looking up a large number of entities, partition the look-ups into batches. See Datastore limits for more details on Datastore limits.

Example
DatastoreDb db = DatastoreDb.Create(projectId, namespaceId);
KeyFactory keyFactory = db.CreateKeyFactory("message");
Entity message = new Entity { Key = keyFactory.CreateIncompleteKey(), ["text"] = "Original" };
db.Insert(message);

using (DatastoreTransaction transaction = db.BeginTransaction())
{
    // Look the message up at the start of the transaction
    Entity fetched1 = transaction.Lookup(message.Key);
    Console.WriteLine((string) fetched1["text"]); // "Original"

    // Update the message outside the transaction
    message["text"] = "Updated";
    db.Update(message);

    // Look up the message up again. We are guaranteed not to see the
    // update because it occurred after the start of the transaction.
    Entity fetched2 = transaction.Lookup(message.Key);
    Console.WriteLine((string) fetched2["text"]); // Still "Original"
}

Lookup(IEnumerable<Key>, CallSettings)

public virtual IReadOnlyList<Entity> Lookup(IEnumerable<Key> keys, CallSettings callSettings = null)

Looks up a collection of entities by key.

Parameters
NameDescription
keysIEnumerable<Key>

The keys to look up. Must not be null, and every element must be non-null and refer to a complete key.

callSettingsCallSettings

If not null, applies overrides to RPC calls.

Returns
TypeDescription
IReadOnlyList<Entity>

A collection of entities with the same size as keys, containing corresponding entity references, or null where the key was not found.

Remarks

This call may perform multiple RPC operations in order to look up all keys.

Example

See Lookup for an example using an alternative overload.

LookupAsync(Key, CallSettings)

public virtual async Task<Entity> LookupAsync(Key key, CallSettings callSettings = null)

Looks up a single entity by key asynchronously.

Parameters
NameDescription
keyKey

The key to look up. Must not be null, and must be complete.

callSettingsCallSettings

If not null, applies overrides to this RPC call.

Returns
TypeDescription
Task<Entity>

The entity with the specified key, or null if no such entity exists.

Remarks

This method simply delegates to LookupAsync(IEnumerable<Key>, CallSettings).

Example

See Lookup for a synchronous example.

LookupAsync(Key[])

public virtual Task<IReadOnlyList<Entity>> LookupAsync(params Key[] keys)

Looks up a collection of entities by key asynchronously.

Parameter
NameDescription
keysKey[]

The keys to look up. Must not be null, and every element must be non-null and refer to a complete key.

Returns
TypeDescription
Task<IReadOnlyList<Entity>>

A collection of entities with the same size as keys, containing corresponding entity references, or null where the key was not found.

Remarks

This call may perform multiple RPC operations in order to look up all keys.

This overload does not support the CallSettings to be specified due to restrictions with methods containing a parameter array and optional parameters. It simply delegates to LookupAsync(IEnumerable<Key>, CallSettings), passing in a null value for the call settings.

Datastore limits the number of entities that can be looked up in a single operation. When looking up a large number of entities, partition the look-ups into batches. See Datastore limits for more details on Datastore limits.

Example

See Lookup for a synchronous example.

LookupAsync(IEnumerable<Key>, CallSettings)

public virtual Task<IReadOnlyList<Entity>> LookupAsync(IEnumerable<Key> keys, CallSettings callSettings = null)

Looks up a collection of entities by key asynchronously.

Parameters
NameDescription
keysIEnumerable<Key>

The keys to look up. Must not be null, and every element must be non-null and refer to a complete key.

callSettingsCallSettings

If not null, applies overrides to RPC calls.

Returns
TypeDescription
Task<IReadOnlyList<Entity>>

A collection of entities with the same size as keys, containing corresponding entity references, or null where the key was not found.

Remarks

This call may perform multiple RPC operations in order to look up all keys.

Example

See Lookup for a synchronous example.

Rollback(CallSettings)

public virtual RollbackResponse Rollback(CallSettings callSettings = null)

Rolls back this transaction.

Parameter
NameDescription
callSettingsCallSettings

If not null, applies overrides to RPC calls.

Returns
TypeDescription
RollbackResponse
Remarks

This method is rarely useful explicitly; the Dispose() method rolls back the transaction if it is still active, so a using statement is normally preferable to this.

Example

See [RollbackAsync] for an asynchronous example.

Exceptions
TypeDescription
InvalidOperationException

The transaction has already been committed or rolled back.

RollbackAsync(CallSettings)

public virtual Task<RollbackResponse> RollbackAsync(CallSettings callSettings = null)

Rolls back this transaction asynchronously.

Parameter
NameDescription
callSettingsCallSettings

If not null, applies overrides to RPC calls.

Returns
TypeDescription
Task<RollbackResponse>
Remarks

This method is rarely useful explicitly; the Dispose() method rolls back the transaction if it is still active, so a using statement is normally preferable to this.

Example
DatastoreDb db = DatastoreDb.Create(projectId, namespaceId);
KeyFactory keyFactory = db.CreateKeyFactory("message");

// Dispose automatically rolls back an uncommitted transaction synchronously.
// To roll back asynchronously, 
bool committed = false;
DatastoreTransaction transaction = await db.BeginTransactionAsync();
try
{
    Entity message = new Entity
    {
        Key = keyFactory.CreateIncompleteKey(),
        ["text"] = "Hello",
    };
    // This adds the entity to a collection in memory: nothing
    // is sent to the server.
    db.Insert(message);

    // Attempt to commit the transaction asynchronously.
    await transaction.CommitAsync();
    committed = true;
}
finally
{
    if (!committed)
    {
        // Roll back asynchronously if anything failed.
        await transaction.RollbackAsync();
    }
}
Exceptions
TypeDescription
InvalidOperationException

The transaction has already been committed or rolled back.

RunQuery(GqlQuery, CallSettings)

public virtual DatastoreQueryResults RunQuery(GqlQuery query, CallSettings callSettings = null)

Runs the given query eagerly in this transaction, retrieving all results in memory and indicating whether more results may be available beyond the query's limit. Use this method when your query has a limited number of results, for example to build a web application which fetches results in pages.

Parameters
NameDescription
queryGqlQuery

The query to execute. Must not be null.

callSettingsCallSettings

If not null, applies overrides to RPC calls.

Returns
TypeDescription
DatastoreQueryResults

The complete query results.

Remarks

Using a transaction ensures that a commit operation will fail if any of the entities returned by this query have been modified while the transaction is active. Note that modifications performed as part of this operation are not reflected in the query results.

The default implementation of this method delegates to RunQueryLazily(GqlQuery, CallSettings) and calls GetAllResults() on the return value.

Example
DatastoreDb db = DatastoreDb.Create(projectId, namespaceId);
KeyFactory keyFactory = db.CreateKeyFactory("player");

// Prepare the data: a player with two game child entities
Entity player = new Entity
{
    Key = keyFactory.CreateIncompleteKey(),
    ["name"] = "Sophie"
};
Key playerKey = db.Insert(player);
Entity game1 = new Entity
{
    Key = playerKey.WithElement(new PathElement { Kind = "game" }),
    ["score"] = 10,
    ["timestamp"] = new DateTime(2017, 2, 16, 8, 35, 0, DateTimeKind.Utc)
};
Entity game2 = new Entity
{
    Key = playerKey.WithElement(new PathElement { Kind = "game" }),
    ["score"] = 25,
    ["timestamp"] = new DateTime(2017, 3, 15, 10, 35, 0, DateTimeKind.Utc)
};
db.Insert(game1, game2);

// Perform a query within a transaction
using (DatastoreTransaction transaction = db.BeginTransaction())
{
    // Any query executed in a transaction must at least have an ancestor filter.
    GqlQuery query = new GqlQuery
    {
        QueryString = "SELECT * FROM game WHERE __key__ HAS ANCESTOR @player LIMIT @limit",
        NamedBindings = {
            { "player", playerKey },
            { "limit", 10 }
        }
    };
    DatastoreQueryResults results = db.RunQuery(query);
    // RunQuery fetches all the results into memory in a single call.
    // Constrast this with RunQueryLazily, which merely prepares an enumerable
    // query. Always specify a limit when you use RunQuery, to avoid running
    // out of memory.
    foreach (Entity entity in results.Entities)
    {
        Console.WriteLine(entity);
    }
}

RunQuery(Query, CallSettings)

public virtual DatastoreQueryResults RunQuery(Query query, CallSettings callSettings = null)

Runs the given query eagerly in this transaction, retrieving all results in memory and indicating whether more results may be available beyond the query's limit. Use this method when your query has a limited number of results, for example to build a web application which fetches results in pages.

Parameters
NameDescription
queryQuery

The query to execute. Must not be null.

callSettingsCallSettings

If not null, applies overrides to RPC calls.

Returns
TypeDescription
DatastoreQueryResults

The complete query results.

Remarks

Using a transaction ensures that a commit operation will fail if any of the entities returned by this query have been modified while the transaction is active. Note that modifications performed as part of this operation are not reflected in the query results.

The default implementation of this method delegates to RunQueryLazily(Query, CallSettings) and calls GetAllResults() on the return value.

Example
DatastoreDb db = DatastoreDb.Create(projectId, namespaceId);
KeyFactory keyFactory = db.CreateKeyFactory("player");

// Prepare the data: a player with two game child entities
Entity player = new Entity
{
    Key = keyFactory.CreateIncompleteKey(),
    ["name"] = "Sophie"
};
Key playerKey = db.Insert(player);
Entity game1 = new Entity
{
    Key = playerKey.WithElement(new PathElement { Kind = "game" }),
    ["score"] = 10,
    ["timestamp"] = new DateTime(2017, 2, 16, 8, 35, 0, DateTimeKind.Utc)
};
Entity game2 = new Entity
{
    Key = playerKey.WithElement(new PathElement { Kind = "game" }),
    ["score"] = 25,
    ["timestamp"] = new DateTime(2017, 3, 15, 10, 35, 0, DateTimeKind.Utc)
};
db.Insert(game1, game2);

// Perform a query within a transaction
using (DatastoreTransaction transaction = db.BeginTransaction())
{
    // Any query executed in a transaction must at least have an ancestor filter.
    Query query = new Query("game")
    {
        Filter = Filter.HasAncestor(playerKey),
        Limit = 10
    };
    DatastoreQueryResults results = db.RunQuery(query);
    // RunQuery fetches all the results into memory in a single call.
    // Constrast this with RunQueryLazily, which merely prepares an enumerable
    // query. Always specify a limit when you use RunQuery, to avoid running
    // out of memory.
    foreach (Entity entity in results.Entities)
    {
        Console.WriteLine(entity);
    }
}

RunQueryAsync(GqlQuery, CallSettings)

public virtual Task<DatastoreQueryResults> RunQueryAsync(GqlQuery query, CallSettings callSettings = null)

Runs the given query eagerly and asynchronously in this transaction, retrieving all results in memory and indicating whether more results may be available beyond the query's limit. Use this method when your query has a limited number of results, for example to build a web application which fetches results in pages.

Parameters
NameDescription
queryGqlQuery

The query to execute. Must not be null.

callSettingsCallSettings

If not null, applies overrides to RPC calls.

Returns
TypeDescription
Task<DatastoreQueryResults>

A task representing the asynchronous operation. The result of the task is the complete set of query results.

Remarks

Using a transaction ensures that a commit operation will fail if any of the entities returned by this query have been modified while the transaction is active. Note that modifications performed as part of this operation are not reflected in the query results.

The default implementation of this method delegates to RunQueryLazilyAsync(GqlQuery, CallSettings) and calls GetAllResultsAsync() on the return value.

Example

See RunQuery for a synchronous example.

RunQueryAsync(Query, CallSettings)

public virtual Task<DatastoreQueryResults> RunQueryAsync(Query query, CallSettings callSettings = null)

Runs the given query eagerly and asynchronously in this transaction, retrieving all results in memory and indicating whether more results may be available beyond the query's limit. Use this method when your query has a limited number of results, for example to build a web application which fetches results in pages.

Parameters
NameDescription
queryQuery

The query to execute. Must not be null.

callSettingsCallSettings

If not null, applies overrides to RPC calls.

Returns
TypeDescription
Task<DatastoreQueryResults>

A task representing the asynchronous operation. The result of the task is the complete set of query results.

Remarks

Using a transaction ensures that a commit operation will fail if any of the entities returned by this query have been modified while the transaction is active. Note that modifications performed as part of this operation are not reflected in the query results.

The default implementation of this method delegates to RunQueryLazilyAsync(Query, CallSettings) and calls GetAllResultsAsync() on the return value.

Example

See RunQueryLazily for a synchronous example.

RunQueryLazily(GqlQuery, CallSettings)

public virtual LazyDatastoreQuery RunQueryLazily(GqlQuery gqlQuery, CallSettings callSettings = null)

Lazily executes the given GQL query in this transaction.

Parameters
NameDescription
gqlQueryGqlQuery

The query to execute. Must not be null.

callSettingsCallSettings

If not null, applies overrides to RPC calls.

Returns
TypeDescription
LazyDatastoreQuery

A LazyDatastoreQuery representing the result of the query.

Remarks

Using a transaction ensures that a commit operation will fail if any of the entities returned by this query have been modified while the transaction is active. Note that modifications performed as part of this operation are not reflected in the query results.

The results are requested lazily: no API calls will be made until the application starts iterating over the results. Iterating over the same LazyDatastoreQuery object multiple times will execute the query again, potentially returning different results.

Example
DatastoreDb db = DatastoreDb.Create(projectId, namespaceId);
KeyFactory keyFactory = db.CreateKeyFactory("player");

// Prepare the data: a player with two game child entities
Entity player = new Entity
{
    Key = keyFactory.CreateIncompleteKey(),
    ["name"] = "Sophie"
};
Key playerKey = db.Insert(player);
Entity game1 = new Entity
{
    Key = playerKey.WithElement(new PathElement { Kind = "game" }),
    ["score"] = 10,
    ["timestamp"] = new DateTime(2017, 2, 16, 8, 35, 0, DateTimeKind.Utc)
};
Entity game2 = new Entity
{
    Key = playerKey.WithElement(new PathElement { Kind = "game" }),
    ["score"] = 25,
    ["timestamp"] = new DateTime(2017, 3, 15, 10, 35, 0, DateTimeKind.Utc)
};
db.Insert(game1, game2);

// Perform a query within a transaction
using (DatastoreTransaction transaction = db.BeginTransaction())
{
    // Any query executed in a transaction must at least have an ancestor filter.
    GqlQuery query = new GqlQuery
    {
        QueryString = "SELECT * FROM game WHERE __key__ HAS ANCESTOR @player",
        NamedBindings = { { "player", playerKey } }
    };
    LazyDatastoreQuery results = db.RunQueryLazily(query);
    // LazyDatastoreQuery implements IEnumerable<Entity>, but you can
    // call AsResponses() to see the raw RPC responses, or
    // GetAllResults() to get all the results into memory, complete with
    // the end cursor and the reason for the query finishing.
    foreach (Entity entity in results)
    {
        Console.WriteLine(entity);
    }
}

RunQueryLazily(Query, CallSettings)

public virtual LazyDatastoreQuery RunQueryLazily(Query query, CallSettings callSettings = null)

Lazily executes the given structured query in this transaction.

Parameters
NameDescription
queryQuery

The query to execute. Must not be null.

callSettingsCallSettings

If not null, applies overrides to RPC calls.

Returns
TypeDescription
LazyDatastoreQuery

A LazyDatastoreQuery representing the the lazy query results.

Remarks

Using a transaction ensures that a commit operation will fail if any of the entities returned by this query have been modified while the transaction is active. Note that modifications performed as part of this operation are not reflected in the query results.

The results are requested lazily: no API calls will be made until the application starts iterating over the results. Iterating over the same LazyDatastoreQuery object multiple times will execute the query again, potentially returning different results.

Example
DatastoreDb db = DatastoreDb.Create(projectId, namespaceId);
KeyFactory keyFactory = db.CreateKeyFactory("player");

// Prepare the data: a player with two game child entities
Entity player = new Entity
{
    Key = keyFactory.CreateIncompleteKey(),
    ["name"] = "Sophie"
};
Key playerKey = db.Insert(player);
Entity game1 = new Entity
{
    Key = playerKey.WithElement(new PathElement { Kind = "game" }),
    ["score"] = 10,
    ["timestamp"] = new DateTime(2017, 2, 16, 8, 35, 0, DateTimeKind.Utc)
};
Entity game2 = new Entity
{
    Key = playerKey.WithElement(new PathElement { Kind = "game" }),
    ["score"] = 25,
    ["timestamp"] = new DateTime(2017, 3, 15, 10, 35, 0, DateTimeKind.Utc)
};
db.Insert(game1, game2);

// Perform a query within a transaction
using (DatastoreTransaction transaction = db.BeginTransaction())
{
    // Any query executed in a transaction must at least have an ancestor filter.
    Query query = new Query("game")
    {
        Filter = Filter.HasAncestor(playerKey)
    };
    LazyDatastoreQuery results = db.RunQueryLazily(query);
    // LazyDatastoreQuery implements IEnumerable<Entity>, but you can
    // call AsResponses() to see the raw RPC responses, or
    // GetAllResults() to get all the results into memory, complete with
    // the end cursor and the reason for the query finishing.
    foreach (Entity entity in results)
    {
        Console.WriteLine(entity);
    }
}

RunQueryLazilyAsync(GqlQuery, CallSettings)

public virtual AsyncLazyDatastoreQuery RunQueryLazilyAsync(GqlQuery gqlQuery, CallSettings callSettings = null)

Lazily executes the given structured query in this transaction for asynchronous consumption.

Parameters
NameDescription
gqlQueryGqlQuery

The query to execute. Must not be null.

callSettingsCallSettings

If not null, applies overrides to RPC calls.

Returns
TypeDescription
AsyncLazyDatastoreQuery

An AsyncLazyDatastoreQuery representing the result of the query.

Remarks

Using a transaction ensures that a commit operation will fail if any of the entities returned by this query have been modified while the transaction is active. Note that modifications performed as part of this operation are not reflected in the query results.

The results are requested lazily: no API calls will be made until the application starts iterating over the results. Iterating over the same LazyDatastoreQuery object multiple times will execute the query again, potentially returning different results.

Example

See RunQueryLazily for a synchronous example.

RunQueryLazilyAsync(Query, CallSettings)

public virtual AsyncLazyDatastoreQuery RunQueryLazilyAsync(Query query, CallSettings callSettings = null)

Lazily executes the given structured query in this transaction for asynchronous consumption.

Parameters
NameDescription
queryQuery

The query to execute. Must not be null.

callSettingsCallSettings

If not null, applies overrides to RPC calls.

Returns
TypeDescription
AsyncLazyDatastoreQuery

An AsyncLazyDatastoreQuery representing the result of the query.

Remarks

Using a transaction ensures that a commit operation will fail if any of the entities returned by this query have been modified while the transaction is active. Note that modifications performed as part of this operation are not reflected in the query results.

The results are requested lazily: no API calls will be made until the application starts iterating over the results. Iterating over the same LazyDatastoreQuery object multiple times will execute the query again, potentially returning different results.

Example

See RunQueryLazily for a synchronous example.

Update(Entity[])

public virtual void Update(params Entity[] entities)

Adds update operations for all the specified keys to this transaction.

Parameter
NameDescription
entitiesEntity[]

The entities to update. Must not be null.

Remarks

This method delegates to Update(IEnumerable<Entity>).

Example
DatastoreDb db = DatastoreDb.Create(projectId, namespaceId);
KeyFactory keyFactory = db.CreateKeyFactory("book");
Entity book = new Entity
{
    Key = keyFactory.CreateIncompleteKey(),
    ["author"] = "Harper Lee",
    ["title"] = "Tequila Mockingbird",
    ["publication_date"] = new DateTime(1960, 7, 11, 0, 0, 0, DateTimeKind.Utc),
    ["genres"] = new[] { "Southern drama", "Courtroom drama", "Bildungsroman" }
};
db.Insert(book);

using (DatastoreTransaction transaction = db.BeginTransaction())
{
    // Correct the typo in memory
    book["title"] = "To Kill a Mockingbird";
    // This adds the entity to a collection of mutations in memory: nothing
    // is sent to the server.
    transaction.Update(book);
    // Without the Commit call, the transaction will automatically
    // be rolled back. The Commit call performs all the mutations
    // within the transaction.
    transaction.Commit();
}

Update(IEnumerable<Entity>)

public virtual void Update(IEnumerable<Entity> entities)

Adds update operations for all the specified keys to this transaction.

Parameter
NameDescription
entitiesIEnumerable<Entity>

The entities to update. Must not be null.

Example

See Update for an example using an alternative overload.

Upsert(Entity[])

public virtual void Upsert(params Entity[] entities)

Adds upsert operations for all the specified keys to this transaction.

Parameter
NameDescription
entitiesEntity[]

The entities to upsert. Must not be null.

Remarks

This method delegates to Upsert(IEnumerable<Entity>).

Example
DatastoreDb db = DatastoreDb.Create(projectId, namespaceId);
KeyFactory keyFactory = db.CreateKeyFactory("book");
Entity book1 = new Entity
{
    Key = keyFactory.CreateIncompleteKey(),
    ["author"] = "Harper Lee",
    ["title"] = "Tequila Mockingbird",
    ["publication_date"] = new DateTime(1960, 7, 11, 0, 0, 0, DateTimeKind.Utc),
    ["genres"] = new[] { "Southern drama", "Courtroom drama", "Bildungsroman" }
};
db.Insert(book1);

using (DatastoreTransaction transaction = db.BeginTransaction())
{
    // Correct the typo in memory
    book1["title"] = "To Kill a Mockingbird";

    Entity book2 = new Entity
    {
        Key = keyFactory.CreateIncompleteKey(),
        ["author"] = "Charlotte Brontë",
        ["title"] = "Jane Eyre",
        ["publication_date"] = new DateTime(1847, 10, 16, 0, 0, 0, DateTimeKind.Utc),
        ["genres"] = new[] { "Gothic", "Romance", "Bildungsroman" }
    };

    // This adds the entities to a collection of mutations in memory: nothing
    // is sent to the server.
    transaction.Upsert(book1, book2);
    // Without the Commit call, the transaction will automatically
    // be rolled back. The Commit call performs all the mutations
    // within the transaction.
    transaction.Commit();
}

Upsert(IEnumerable<Entity>)

public virtual void Upsert(IEnumerable<Entity> entities)

Adds upsert operations for all the specified keys to this transaction.

Parameter
NameDescription
entitiesIEnumerable<Entity>

The entities to upsert. Must not be null.

Example

See Upsert for an example using an alternative overload.