private async Task UnrelatedTransactionsDoNotConflict(IDgraphClient client) { var txn1 = client.NewTransaction(); var txn2 = client.NewTransaction(); var personTxn1 = MintAPerson("Alfred Name"); var personTxn2 = MintAPerson("Fank Person"); // Name has term and exact indexes, so these shouldn't clash var transactionResultTxn1 = await txn1.Mutate(new RequestBuilder(). WithMutations(new MutationBuilder { SetJson = JsonConvert.SerializeObject(personTxn1) })); AssertResultIsSuccess(transactionResultTxn1); personTxn1.Uid = transactionResultTxn1.Value.Uids[personTxn1.Uid.Substring(2)]; var transactionResultTxn2 = await txn2.Mutate(new RequestBuilder(). WithMutations(new MutationBuilder { SetJson = JsonConvert.SerializeObject(personTxn2) })); AssertResultIsSuccess(transactionResultTxn2); personTxn2.Uid = transactionResultTxn2.Value.Uids[personTxn2.Uid.Substring(2)]; // Can't see the other result var queryByName = await txn2.QueryWithVars( FriendQueries.QueryByName, new Dictionary <string, string> { { "$name", personTxn1.Name } }); AssertResultIsSuccess(queryByName); queryByName.Value.Json.Should().Be("{\"q\":[]}"); // Cause the mutates can't clash these should be ok AssertResultIsSuccess(await txn1.Commit()); AssertResultIsSuccess(await txn2.Commit()); // both are there queryByName = await client.NewReadOnlyTransaction().QueryWithVars( FriendQueries.QueryByName, new Dictionary <string, string> { { "$name", personTxn1.Name } }); AssertResultIsSuccess(queryByName); FriendQueries.AssertStringIsPerson(queryByName.Value.Json, personTxn1); queryByName = await client.NewReadOnlyTransaction().QueryWithVars( FriendQueries.QueryByName, new Dictionary <string, string> { { "$name", personTxn2.Name } }); AssertResultIsSuccess(queryByName); FriendQueries.AssertStringIsPerson(queryByName.Value.Json, personTxn2); }
private async Task ConflictingTransactionsDontBothSucceed(IDgraphClient client) { var txn1 = client.NewTransaction(); var txn2 = client.NewTransaction(); var personTxn1 = MintAPerson("Bill Person"); var personTxn2 = MintAPerson("Jane Person"); var transactionResultTxn1 = await txn1.Mutate(new RequestBuilder(). WithMutations(new MutationBuilder { SetJson = JsonConvert.SerializeObject(personTxn1) })); AssertResultIsSuccess(transactionResultTxn1); personTxn1.Uid = transactionResultTxn1.Value.Uids[personTxn1.Uid.Substring(2)]; var transactionResultTxn2 = await txn2.Mutate(new RequestBuilder(). WithMutations(new MutationBuilder { SetJson = JsonConvert.SerializeObject(personTxn2) })); AssertResultIsSuccess(transactionResultTxn2); // Name has term and exact indexes, so these clash on 'Person' term AssertResultIsSuccess(await txn1.Commit()); var txn2Result = await txn2.Commit(); txn2Result.IsFailed.Should().BeTrue(); // Not 100% sure about this quirk. Pretty sure this is how is how // dgo does it, but I wonder that it should be in an error state? txn2.TransactionState.Should().Be(TransactionState.Committed); // txn1 is there var queryByName = await client.NewReadOnlyTransaction().QueryWithVars( FriendQueries.QueryByName, new Dictionary <string, string> { { "$name", personTxn1.Name } }); AssertResultIsSuccess(queryByName); FriendQueries.AssertStringIsPerson(queryByName.Value.Json, personTxn1); // txn2 had no effect queryByName = await client.NewReadOnlyTransaction().QueryWithVars( FriendQueries.QueryByName, new Dictionary <string, string> { { "$name", personTxn2.Name } }); AssertResultIsSuccess(queryByName); queryByName.Value.Json.Should().Be("{\"q\":[]}"); }
private async Task AlterAPerson(IDgraphClient client) { using (var transaction = client.NewTransaction()) { Person3.Friends.Add(Person2); // This will serialize the whole object. You might not want to // do that, and maybe only add in the bits that have changed // instead. var json = JsonConvert.SerializeObject(Person3); var result = await transaction.Mutate(json); AssertResultIsSuccess(result, "Mutation failed"); // no nodes were allocated result.Value.Count.Should().Be(0); await transaction.Commit(); } var queryPerson = await client.Query(FriendQueries.QueryByUid(Person3.Uid)); AssertResultIsSuccess(queryPerson, "Query failed"); FriendQueries.AssertStringIsPerson(queryPerson.Value, Person3); }
private async Task DiscardedTransactionsHaveNoEffect(IDgraphClient client) { var txn1 = client.NewTransaction(); var person = MintAPerson(nameof(DiscardedTransactionsHaveNoEffect)); var json = JsonConvert.SerializeObject(person); var transactionResult = await txn1.Mutate(json); AssertResultIsSuccess(transactionResult); person.Uid = transactionResult.Value[person.Uid.Substring(2)]; await txn1.Discard(); // Can we see it var queryByName = await client.QueryWithVars( FriendQueries.QueryByName, new Dictionary <string, string> { { "$name", person.Name } }); AssertResultIsSuccess(queryByName); queryByName.Value.Should().Be("{\"q\":[]}"); // Can we see it in the uid (note that uid queries always return the // uid ... we are interested if returns the actual person or not) var queryByUid = await client.Query(FriendQueries.QueryByUid(person.Uid)); AssertResultIsSuccess(queryByUid); queryByUid.Value.Should().Be($"{{\"q\":[{{\"uid\":\"{person.Uid}\"}}]}}"); }
private async Task TransactionsAreSerlializable(IDgraphClient client) { var txn1 = client.NewTransaction(); var txn2 = client.NewTransaction(); var person = MintAPerson(nameof(TransactionsAreSerlializable)); var json = JsonConvert.SerializeObject(person); var transactionResult = await txn1.Mutate(new RequestBuilder(). WithMutations(new MutationBuilder { SetJson = json })); AssertResultIsSuccess(transactionResult); person.Uid = transactionResult.Value.Uids[person.Uid.Substring(2)]; // Can we see it var queryByName = await txn2.QueryWithVars( FriendQueries.QueryByName, new Dictionary <string, string> { { "$name", person.Name } }); AssertResultIsSuccess(queryByName); queryByName.Value.Json.Should().Be("{\"q\":[]}"); AssertResultIsSuccess(await txn1.Commit()); // can we see it now - still in txn2 queryByName = await txn2.QueryWithVars( FriendQueries.QueryByName, new Dictionary <string, string> { { "$name", person.Name } }); AssertResultIsSuccess(queryByName); queryByName.Value.Json.Should().Be("{\"q\":[]}"); await txn2.Discard(); }
private async Task AddThreePeople(IDgraphClient client) { using (var transaction = client.NewTransaction()) { // Serialize the objects to json in whatever way works best for you. // // The CamelCaseNamingStrategy attribute on the type means these // get serialised with initial lower case. var personList = new List <Person> { Person1, Person2, Person3 }; var json = JsonConvert.SerializeObject(personList); // There's two mutation options. For just one mutation, use this version var result = await transaction.Mutate(setJson : json); // For more complicated multi-mutation requests or upsert mutations // see the upsert test. AssertResultIsSuccess(result, "Mutation failed"); // The payload of the result contains a node->uid map of newly // allocated nodes. If the nodes don't have uid names in the // mutation, then the map is like // // {{ "blank-0": "0xa", "blank-1": "0xb", "blank-2": "0xc", ... }} // // If the // mutation has '{ "uid": "_:Person1" ... }' etc, then the blank // node map is like // // {{ "Person3": "0xe", "Person1": "0xf", "Person2": "0xd", ... }} result.Value.Uids.Count.Should().Be(3); // It's no required to save the uid's like this, but can work // nicely ... and makes these tests easier to keep track of. Person1.Uid = result.Value.Uids[Person1.Uid.Substring(2)]; Person2.Uid = result.Value.Uids[Person2.Uid.Substring(2)]; Person3.Uid = result.Value.Uids[Person3.Uid.Substring(2)]; var transactionResult = await transaction.Commit(); AssertResultIsSuccess(transactionResult); } }
private async Task NoDirtyReads(IDgraphClient client) { var txn1 = client.NewTransaction(); var person = MintAPerson(nameof(NoDirtyReads)); var json = JsonConvert.SerializeObject(person); var transactionResult = await txn1.Mutate(new RequestBuilder(). WithMutations(new MutationBuilder { SetJson = json })); AssertResultIsSuccess(transactionResult, "Mutation failed"); person.Uid = transactionResult.Value.Uids[person.Uid.Substring(2)]; // Can we see this from another transaction? var queryByName = await client.NewReadOnlyTransaction().QueryWithVars( FriendQueries.QueryByName, new Dictionary <string, string> { { "$name", person.Name } }); AssertResultIsSuccess(queryByName); queryByName.Value.Json.Should().Be("{\"q\":[]}"); // Can we see it in the uid (note that uid queries always return the // uid ... we are interested if returns the actual person or not) var queryByUid = await client.NewReadOnlyTransaction(). Query(FriendQueries.QueryByUid(person.Uid)); AssertResultIsSuccess(queryByUid); queryByUid.Value.Json.Should().Be($"{{\"q\":[{{\"uid\":\"{person.Uid}\"}}]}}"); AssertResultIsSuccess(await txn1.Commit()); queryByName = await client.NewReadOnlyTransaction().QueryWithVars( FriendQueries.QueryByName, new Dictionary <string, string> { { "$name", person.Name } }); AssertResultIsSuccess(queryByName); FriendQueries.AssertStringIsPerson(queryByName.Value.Json, person); }
private async Task DeleteAPerson(IDgraphClient client) { using (var transaction = client.NewTransaction()) { // delete a node by passing JSON like this to delete var deleteResult = await transaction.Mutate( deleteJson : $"{{\"uid\": \"{Person1.Uid}\"}}"); AssertResultIsSuccess(deleteResult, "Delete failed"); var transactionResult = await transaction.Commit(); AssertResultIsSuccess(transactionResult); } // that person should be gone... var queryPerson1 = await client.NewReadOnlyTransaction(). Query(FriendQueries.QueryByUid(Person1.Uid)); AssertResultIsSuccess(queryPerson1, "Query failed"); // no matter what uid you query for, Dgraph always succeeds :-( // e.g. on a fresh dgraph with no uids allocated // { q(func: uid(0x44444444)) { uid }} // will answer // "q": [ { "uid": "0x44444444" } ] // // so the only way to test that the node is deleted, // is to test that we got only that back queryPerson1.Value.Json.Should().Be($"{{\"q\":[{{\"uid\":\"{Person1.Uid}\"}}]}}"); // ... but watch out, Dgraph can leave dangling references // e.g. there are some edges in our graph that still point to // Person 1 - we've just removed all it's outgoing edges. var queryPerson3 = await client.NewReadOnlyTransaction(). Query(FriendQueries.QueryByUid(Person3.Uid)); AssertResultIsSuccess(queryPerson3, "Query failed"); var person3 = JObject.Parse(queryPerson3.Value.Json)["q"][0].ToObject <Person>(); person3.Friends.Count.Should().Be(2); }
private async Task DeleteAPerson(IDgraphClient client) { using (var transaction = client.NewTransaction()) { // delete a node by passing JSON like this to delete var deleteResult = await transaction.Delete($"{{\"uid\": \"{Person1.Uid}\"}}"); AssertResultIsSuccess(deleteResult, "Delete failed"); await transaction.Commit(); } // that person should be gone... var queryPerson1 = await client.Query(FriendQueries.QueryByUid(Person1.Uid)); AssertResultIsSuccess(queryPerson1, "Query failed"); // no matter what uid you query for, Dgraph always succeeds :-( // e.g. on a fresh dgraph with no uids allocated // { q(func: uid(0x44444444)) { uid }} // will answer // "q": [ { "uid": "0x44444444" } ] // // so the only way to test that the node is deleted, // is to test that we got only that back queryPerson1.Value.Should().Be($"{{\"q\":[{{\"uid\":\"{Person1.Uid}\"}}]}}"); // ----------------------------------------------------------- // ... but watch out, Dgraph can leave dangling references :-( // ----------------------------------------------------------- var queryPerson3 = await client.Query(FriendQueries.QueryByUid(Person3.Uid)); AssertResultIsSuccess(queryPerson3, "Query failed"); var person3 = JObject.Parse(queryPerson3.Value) ["q"][0].ToObject <Person>(); person3.Friends.Count.Should().Be(2); // You'll need something like GraphSchema to handle things like // cascading deletes etc. and clean up automatically :-) }
static async Task Main(string[] args) { using (IDgraphClient client = DgraphDotNet.Clients.NewDgraphClient()) { client.Connect("127.0.0.1:9080"); await client.AlterSchema( "Username: string @index(hash) .\n" + "Password: password ."); var schemaResult = await client.SchemaQuery(); if (schemaResult.IsFailed) { Console.WriteLine($"Something went wrong getting schema."); return; } Console.WriteLine("Queried schema and got :"); foreach (var predicate in schemaResult.Value.Schema) { Console.WriteLine(predicate.ToString()); } while (true) { Console.WriteLine("Hi, please enter your new username"); var username = Console.ReadLine(); // use Upsert to test for a node and value, and create if // not already in the graph as an atomic operation. var result = await client.Upsert( "Username", GraphValue.BuildStringValue(username), $"{{\"uid\": \"_:myBlank\", \"Username\": \"{username}\"}}", "myBlank"); if (result.IsFailed) { Console.WriteLine("Something went wrong : " + result); continue; } var(node, existed) = result.Value; if (existed) { Console.WriteLine("This user already existed. Try another username."); continue; } Console.WriteLine("Hi, please enter a password for the new user"); var password = Console.ReadLine(); using (var txn = client.NewTransaction()) { var mutation = txn.NewMutation(); var property = Clients.BuildProperty(node, "Password", GraphValue.BuildPasswordValue(password)); if (property.IsFailed) { // ... something went wrong Console.Write("uhh"); } else { mutation.AddProperty(property.Value); var err = await mutation.Submit(); if (err.IsFailed) { // ... something went wrong Console.Write(err); } } await txn.Commit(); } } } }