Skip to content

Increase ExpressionBuilder and WhereExpression[Graph] access from internal to public#101

Merged
SimonCropp merged 3 commits intoSimonCropp:masterfrom
techniq:master
Mar 15, 2019
Merged

Increase ExpressionBuilder and WhereExpression[Graph] access from internal to public#101
SimonCropp merged 3 commits intoSimonCropp:masterfrom
techniq:master

Conversation

@techniq
Copy link
Copy Markdown
Contributor

@techniq techniq commented Mar 14, 2019

Description

Increasing the default access of ExpressionBuilder and WhereExpression will allow direct usage in non-Query/Navigation Fields which is helpful for aggregate/non-entity returning fields.

For example, I expose some *Summary fields to provide aggregate rollups of some data, but would like to pass the same where argument I pass to the listing fields (ex. AllBalances)

For example, this change will allow the following usage:

Field<ListGraphType<BalanceSummaryGraph>>(
    name: "BalanceSummary",
    arguments: new QueryArguments(
        new QueryArgument<ListGraphType<WhereExpressionGraph>> { Name = "where" }
    ),
    resolve: context =>
    {
        var userContext = (context.UserContext as FinanceUserContext);
        var dbContext = userContext.DbContext;
        var query = dbContext.Balances as IQueryable<Balance>;

        if (context.HasArgument("where"))
        {
            var whereExpressions = context.GetArgument<List<WhereExpression>>("where");
            var predicate = ExpressionBuilder<Balance>.BuildPredicate(where);
            query = query.Where(predicate);
        }

        var results = from q in query
                      group q by new { q.PeriodStart } into g
                      select new BalanceSummary {
                        PeriodStart = g.Key.PeriodStart,
                        Actual = g.Sum(x => x.Actual),
                        Budgeted = g.Sum(x => x.Budgeted),
                        Variance = g.Sum(x => x.Variance)
                      };

        return results;
    });

The solution

I initially tried to use AddQueryConnectionField to add the BalanceSummary field and leverage the application of the where argument imperatively, but it was raising an exception in IncludeAppender probably because the BalanceSummary class is not an entity model, but just a DTO/POCO.

public class BalanceSummaryGraph : ObjectGraphType<BalanceSummary>
{
    public BalanceSummaryGraph()
    {
        Field(x => x.PeriodStart);

        Field(x => x.Actual, nullable: true);
        Field(x => x.Budgeted, nullable: true);
        Field(x => x.Variance, nullable: true);
        Field(x => x.BeginningBalance, nullable: true);
    }
}

public class BalanceSummary
{
    public DateTime PeriodStart { get; set; }

    public decimal? Actual { get; set; }
    public decimal? Budgeted { get; set; }
    public decimal? Variance { get; set; }
    public decimal? BeginningBalance { get; set; }
}

Exposing these classes gives greater control when needed as well.

@SimonCropp
Copy link
Copy Markdown
Owner

can u add a test that illustrates the usage. and also add some doco on that use case

@techniq
Copy link
Copy Markdown
Contributor Author

techniq commented Mar 14, 2019 via email

@techniq
Copy link
Copy Markdown
Contributor Author

techniq commented Mar 14, 2019

Sorry, this might take me a little longer to update. I needed to get the tests running on my Mac, which took me a little. Here's the steps I did (in case others find this useful, or I need to remember later... 😄 )


  • Setup tests to use my Docker SQL Server container

Update the connection string from

ConnectionString = $@"Data Source=.\SQLExpress;Database={dbName}; Integrated Security=True;Max Pool Size=100;MultipleActiveResultSets=true";

to

ConnectionString = $@"Server=localhost;Database={dbName};User Id=sa;Password=redacted;MultipleActiveResultSets=True";
SqlHelper.EnsureDatabaseExists(ConnectionString);

  • Only run the tests using dotnet core using dotnet test -f netcoreapp2.2 since I don't have 4.7 framework available.

@techniq
Copy link
Copy Markdown
Contributor Author

techniq commented Mar 14, 2019

@SimonCropp Just curious, I noticed the Test project has net472 as a TargetFramework along with netcoreapp2.2, but all the other projects (especially GraphQL.EntityFramework) only have netcoreapp2.2. Is this intentional (for SqlExpress maybe?)? If not, could it be removed?

I needed to remove it to allow the VSCode test runner extension to work, as even specifying -f netcoreapp2.2 in the config, it appears to only be used with dotnet test and not dotnet build.

@techniq
Copy link
Copy Markdown
Contributor Author

techniq commented Mar 14, 2019

@SimonCropp Tests and docs added.

Regarding the docs, I updated defining-graphs.source.md and re-ran the tests so it updated defining-graphs.md, but I also saw some of the other non-source files were updated, and I went ahead and checked those in as well.

See my comment above regarding net472 target framework and any input you have on that. Thanks.

@SimonCropp SimonCropp merged commit c60474f into SimonCropp:master Mar 15, 2019
@SimonCropp SimonCropp added this to the 3.2.0 milestone Mar 15, 2019
@SimonCropp
Copy link
Copy Markdown
Owner

This is now deployed. NuGet may take some time to make it available for download.

thanks for all the work. sorry u had hassle getting it running

@techniq
Copy link
Copy Markdown
Contributor Author

techniq commented Mar 15, 2019

No worries and thanks. I'll pull it down in a bit once I get to work.

Thanks again for the project. It's been working out great. You're likely to get more PRs from me in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants