public PersonMutation(IQueryBuilder <Person> personQueryBuilder, IServiceProvider serviceProvider) { Field <PersonType>( "addPerson", description: "Adds new person.", arguments: new QueryArguments( new QueryArgument <PersonInputType> { Name = "person" } ), resolve: context => { var person = context.GetArgument <Person>("person"); using (var connection = serviceProvider.GetRequiredService <IDbConnection>()) { person.Id = person.MergedToPersonId = PostgreSql.NextIdentity(connection, (Person p) => p.Id); bool success = SqlBuilder .Insert(person) .Execute(connection) > 0; if (success) { var personMapper = new PersonEntityMapper(); var query = SqlBuilder .From <Person>("Person") .Select("FirstName, LastName") .Where("ID = @personId", new { personId = person.Id }); var results = query .Execute(connection, context.FieldAst, personMapper) .Distinct(); return(results.FirstOrDefault()); } return(null); } } ); }
public void EntityMapSucceeds() { var person1 = new Person { FirstName = "Doug", Id = 2, LastName = "Day", MergedToPersonId = 2, }; var person2 = new Person { FirstName = "Douglas", Id = 2, LastName = "Day", MergedToPersonId = 2, }; var email1 = new Email { Address = "*****@*****.**", Id = 2, }; var email2 = new Email { Address = "*****@*****.**", Id = 3, }; var phone = new Phone { Id = 1, Number = "8011234567", Type = PhoneType.Mobile, }; var splitOn = new[] { typeof(Person), typeof(Email), typeof(Phone), }; var personEntityMapper = new PersonEntityMapper(); var graphql = @" { query { firstName lastName id emails { id address } phones { id number type } } }"; var selectionSet = fixture.BuildGraphQLSelection(graphql); var context1 = new EntityMapContext { Items = new object[] { person1, email1, phone, }, SelectionSet = selectionSet, SplitOn = splitOn, }; person1 = personEntityMapper.Map(context1); Assert.Equal(3, context1.MappedCount); Assert.Equal(2, person1.Id); Assert.Equal("Doug", person1.FirstName); Assert.Equal(1, person1.Emails.Count); Assert.Equal(1, person1.Phones.Count); var context2 = new EntityMapContext { Items = new object[] { person2, email2, null, }, SelectionSet = selectionSet, SplitOn = splitOn, }; person2 = personEntityMapper.Map(context2); Assert.Equal(3, context2.MappedCount); // The same reference should have been returned Assert.Same(person1, person2); // A 2nd email was added to person Assert.Equal(2, person1.Emails.Count); }
public PersonQuery( IQueryBuilder <Person> personQueryBuilder, IServiceProvider serviceProvider) { Field <ListGraphType <PersonType> >( "people", description: "A list of people.", resolve: context => { var alias = "person"; var query = SqlBuilder .From <Person>(alias) .OrderBy($"{alias}.Id"); query = personQueryBuilder.Build(query, context.FieldAst, alias); // Create a mapper that understands how to uniquely identify the 'Person' class, // and will deduplicate people as they pass through it var personMapper = new PersonEntityMapper(); using (var connection = serviceProvider.GetRequiredService <IDbConnection>()) { var results = query .Execute(connection, context.FieldAst, personMapper) .Distinct(); return(results); } } ); FieldAsync <ListGraphType <PersonType> >( "peopleAsync", description: "A list of people fetched asynchronously.", resolve: async context => { var alias = "person"; var query = SqlBuilder .From($"Person {alias}") .OrderBy($"{alias}.Id"); query = personQueryBuilder.Build(query, context.FieldAst, alias); // Create a mapper that understands how to uniquely identify the 'Person' class, // and will deduplicate people as they pass through it var personMapper = new PersonEntityMapper(); using (var connection = serviceProvider.GetRequiredService <IDbConnection>()) { connection.Open(); var results = await query.ExecuteAsync(connection, context.FieldAst, personMapper); return(results.Distinct()); } } ); Field <PersonType>( "person", description: "Gets a person by ID.", arguments: new QueryArguments( new QueryArgument <IntGraphType> { Name = "id", Description = "The ID of the person." } ), resolve: context => { var id = context.Arguments["id"]; var alias = "person"; var query = SqlBuilder .From($"Person {alias}") .Where($"{alias}.Id = @id", new { id }) // Even though we're only getting a single person, the process of deduplication // may return several entities, so we sort by ID here for consistency // with test results. .OrderBy($"{alias}.Id"); query = personQueryBuilder.Build(query, context.FieldAst, alias); // Create a mapper that understands how to uniquely identify the 'Person' class, // and will deduplicate people as they pass through it var personMapper = new PersonEntityMapper(); using (var connection = serviceProvider.GetRequiredService <IDbConnection>()) { var results = query .Execute(connection, context.FieldAst, personMapper) .Distinct(); return(results.FirstOrDefault()); } } ); }
public void InsertPerson() { Person person = null; // Ensure inserting a person works and we get IDs back int emailId = -1; int personId = -1; int phoneId = -1; try { using (var db = fixture.GetDbConnection()) { db.Open(); // Get the next identity aggressively, as we need to assign // it to both Id/MergedToPersonId personId = PostgreSql.NextIdentity(db, (Person p) => p.Id); Assert.True(personId > 0); person = new Person { Id = personId, FirstName = "Steven", LastName = "Rollman", MergedToPersonId = personId, }; int insertedCount; insertedCount = SqlBuilder .Insert(person) .Execute(db); Assert.Equal(1, insertedCount); emailId = PostgreSql.NextIdentity(db, (Email e) => e.Id); var email = new Email { Id = emailId, Address = "*****@*****.**", }; var personEmail = new { PersonId = personId, EmailId = emailId, }; phoneId = PostgreSql.NextIdentity(db, (Phone p) => p.Id); var phone = new Phone { Id = phoneId, Number = "8011115555", Type = PhoneType.Mobile, }; var personPhone = new { PersonId = personId, PhoneId = phoneId, }; // Add email and phone number to the person insertedCount = SqlBuilder .Insert(email) .Insert(phone) .Insert("PersonEmail", personEmail) .Insert("PersonPhone", personPhone) .Execute(db); // Ensure all were inserted properly Assert.Equal(4, insertedCount); // Build an entity mapper for person var personMapper = new PersonEntityMapper(); // Query the person from the database var query = SqlBuilder .From <Person>("person") .LeftJoin("PersonEmail personEmail on person.Id = personEmail.Id") .LeftJoin("Email email on personEmail.EmailId = email.Id") .LeftJoin("PersonPhone personPhone on person.Id = personPhone.PersonId") .LeftJoin("Phone phone on personPhone.PhoneId = phone.Id") .Select("person.*, email.*, phone.*") .SplitOn <Person>("Id") .SplitOn <Email>("Id") .SplitOn <Phone>("Id") .Where("person.Id = @id", new { id = personId }); var graphql = @" { person { firstName lastName emails { id address } phones { id number } } }"; var selection = fixture.BuildGraphQLSelection(graphql); person = query .Execute(db, selection, personMapper) .Single(); } // Ensure all inserted data is present Assert.NotNull(person); Assert.Equal(personId, person.Id); Assert.Equal("Steven", person.FirstName); Assert.Equal("Rollman", person.LastName); Assert.Equal(1, person.Emails.Count); Assert.Equal("*****@*****.**", person.Emails[0].Address); Assert.Equal(1, person.Phones.Count); Assert.Equal("8011115555", person.Phones[0].Number); } finally { // Ensure the changes here don't affect other unit tests using (var db = fixture.GetDbConnection()) { if (emailId != default(int)) { SqlBuilder .Delete("PersonEmail", new { EmailId = emailId }) .Delete("Email", new { Id = emailId }) .Execute(db); } if (phoneId != default(int)) { SqlBuilder .Delete("PersonPhone", new { PhoneId = phoneId }) .Delete("Phone", new { Id = phoneId }) .Execute(db); } if (personId != default(int)) { SqlBuilder .Delete <Person>(new { Id = personId }) .Execute(db); } } } }