diff --git a/.travis.yml b/.travis.yml index 7ac38bba9f..9c5e937589 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,12 @@ language: csharp dist: trusty sudo: required -services: +services: - postgresql before_script: - psql -c 'create database JsonApiDotNetCoreExample;' -U postgres mono: none -dotnet: 2.1.105 # https://www.microsoft.com/net/download/linux +dotnet: 2.1.300 # https://www.microsoft.com/net/download/linux branches: only: - master diff --git a/Directory.Build.props b/Directory.Build.props index 346835dd6c..0d034e0c5d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,28 +4,27 @@ netcoreapp2.0 netstandard2.0 - 2.0.1 + 2.1.0 - 2.0.0 - 2.0.0 - 2.0.0 + 2.1.0 + 2.1.0 + 2.1.0 - 2.0.1 - 2.0.1 + 2.1.0 + 2.1.0 - 3.2.6 - 2.0.0 + 4.0.0 + 2.1.0 - 4.4.0 + 4.5.0 - 15.3.0-preview-20170427-09 - 1.1.2 - 2.3.0-beta3-build3705 - 15.0.3 - 4.7.99 + 15.7.2 + 2.3.1 + 22.1.2 + 4.8.3 diff --git a/benchmarks/Benchmarks.csproj b/benchmarks/Benchmarks.csproj index 9f3320575b..60a9a8bf42 100644 --- a/benchmarks/Benchmarks.csproj +++ b/benchmarks/Benchmarks.csproj @@ -5,7 +5,7 @@ Benchmarks - + diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/Restricted/ReadOnlyController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/Restricted/ReadOnlyController.cs index 57fafc8fc6..2515b1ea7a 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Controllers/Restricted/ReadOnlyController.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/Restricted/ReadOnlyController.cs @@ -5,7 +5,7 @@ namespace JsonApiDotNetCoreExample.Controllers.Restricted { [Route("[controller]")] [HttpReadOnly] - public class ReadOnlyController : Controller + public class ReadOnlyController : ControllerBase { [HttpGet] public IActionResult Get() => Ok(); @@ -22,7 +22,7 @@ public class ReadOnlyController : Controller [Route("[controller]")] [NoHttpPost] - public class NoHttpPostController : Controller + public class NoHttpPostController : ControllerBase { [HttpGet] public IActionResult Get() => Ok(); @@ -39,7 +39,7 @@ public class NoHttpPostController : Controller [Route("[controller]")] [NoHttpPatch] - public class NoHttpPatchController : Controller + public class NoHttpPatchController : ControllerBase { [HttpGet] public IActionResult Get() => Ok(); @@ -56,7 +56,7 @@ public class NoHttpPatchController : Controller [Route("[controller]")] [NoHttpDelete] - public class NoHttpDeleteController : Controller + public class NoHttpDeleteController : ControllerBase { [HttpGet] public IActionResult Get() => Ok(); diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/TestValuesController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/TestValuesController.cs index 3443d34b74..a29295c426 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Controllers/TestValuesController.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/TestValuesController.cs @@ -3,7 +3,7 @@ namespace JsonApiDotNetCoreExample.Controllers { [Route("[controller]")] - public class TestValuesController : Controller + public class TestValuesController : ControllerBase { [HttpGet] public IActionResult Get() diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs index de784c129a..f5f3e111d9 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/TodoItemsCustomController.cs @@ -33,17 +33,12 @@ public CustomJsonApiController( } public class CustomJsonApiController - : Controller where T : class, IIdentifiable + : ControllerBase where T : class, IIdentifiable { private readonly ILogger _logger; private readonly IResourceService _resourceService; private readonly IJsonApiContext _jsonApiContext; - protected IActionResult UnprocessableEntity() - { - return new StatusCodeResult(422); - } - protected IActionResult Forbidden() { return new StatusCodeResult(403); diff --git a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj index e588c81b4e..fd657e83bf 100755 --- a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj +++ b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj @@ -25,4 +25,5 @@ + diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.Designer.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.Designer.cs index c86425b00c..c9788bf82f 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.Designer.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.Designer.cs @@ -1,4 +1,4 @@ -// +// using JsonApiDotNetCoreExample.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -7,6 +7,7 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; using System; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace JsonApiDotNetCoreExample.Migrations { diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs index ba19b62ef6..cc696f54bf 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs @@ -1,7 +1,8 @@ -using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using System; using System.Collections.Generic; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace JsonApiDotNetCoreExample.Migrations { diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs index c0794103fe..08c284393e 100755 --- a/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs @@ -1,4 +1,4 @@ -// +// using JsonApiDotNetCoreExample.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -7,6 +7,7 @@ using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage.Internal; using System; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace JsonApiDotNetCoreExample.Migrations { diff --git a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj index eed5f1b09e..efdaa68e5b 100755 --- a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj +++ b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj @@ -18,7 +18,7 @@ - + diff --git a/src/Examples/NoEntityFrameworkExample/Startup.cs b/src/Examples/NoEntityFrameworkExample/Startup.cs index b1f1d05188..711b54cfa3 100755 --- a/src/Examples/NoEntityFrameworkExample/Startup.cs +++ b/src/Examples/NoEntityFrameworkExample/Startup.cs @@ -31,7 +31,7 @@ public Startup(IHostingEnvironment env) public virtual IServiceProvider ConfigureServices(IServiceCollection services) { // Add framework services. - var mvcBuilder = services.AddMvc(); + var mvcBuilder = services.AddMvcCore(); services.AddJsonApi(options => { options.Namespace = "api/v1"; diff --git a/src/Examples/OperationsExample/OperationsExample.csproj b/src/Examples/OperationsExample/OperationsExample.csproj index 02eeabe976..efb3f2b3d4 100644 --- a/src/Examples/OperationsExample/OperationsExample.csproj +++ b/src/Examples/OperationsExample/OperationsExample.csproj @@ -26,4 +26,5 @@ + diff --git a/src/Examples/ReportsExample/ReportsExample.csproj b/src/Examples/ReportsExample/ReportsExample.csproj index bd4b402071..24c01b9a8d 100644 --- a/src/Examples/ReportsExample/ReportsExample.csproj +++ b/src/Examples/ReportsExample/ReportsExample.csproj @@ -13,11 +13,11 @@ - + - + diff --git a/src/Examples/ReportsExample/Startup.cs b/src/Examples/ReportsExample/Startup.cs index 72710681b9..fe476c0406 100644 --- a/src/Examples/ReportsExample/Startup.cs +++ b/src/Examples/ReportsExample/Startup.cs @@ -25,7 +25,7 @@ public Startup(IHostingEnvironment env) public virtual void ConfigureServices(IServiceCollection services) { - var mvcBuilder = services.AddMvc(); + var mvcBuilder = services.AddMvcCore(); services.AddJsonApi(opt => { opt.BuildContextGraph(builder => diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs b/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs index 6fff3a22c8..8c3099dde1 100644 --- a/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs +++ b/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs @@ -5,13 +5,8 @@ namespace JsonApiDotNetCore.Controllers { - public abstract class JsonApiControllerMixin : Controller + public abstract class JsonApiControllerMixin : ControllerBase { - protected IActionResult UnprocessableEntity() - { - return new StatusCodeResult(422); - } - protected IActionResult Forbidden() { return new StatusCodeResult(403); @@ -23,18 +18,19 @@ protected IActionResult Error(Error error) { Errors = new List { error } }; - var result = new ObjectResult(errorCollection); - result.StatusCode = error.StatusCode; - return result; + return new ObjectResult(errorCollection) + { + StatusCode = error.StatusCode + }; } protected IActionResult Errors(ErrorCollection errors) { - var result = new ObjectResult(errors); - result.StatusCode = GetErrorStatusCode(errors); - - return result; + return new ObjectResult(errors) + { + StatusCode = GetErrorStatusCode(errors) + }; } private int GetErrorStatusCode(ErrorCollection errors) diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs index c3b667bc7d..f6db9f0d06 100644 --- a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs +++ b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs @@ -8,7 +8,7 @@ namespace JsonApiDotNetCore.Controllers /// /// A controller to be used for bulk operations as defined in the json:api 1.1 specification /// - public class JsonApiOperationsController : Controller + public class JsonApiOperationsController : ControllerBase { private readonly IOperationsProcessor _operationsProcessor; diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs index 217b5f077b..5e8eeefdd1 100644 --- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs +++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs @@ -23,20 +23,20 @@ public static class IServiceCollectionExtensions public static IServiceCollection AddJsonApi(this IServiceCollection services) where TContext : DbContext { - var mvcBuilder = services.AddMvc(); - return AddJsonApi(services, (opt) => { }, mvcBuilder); + var mvcBuilder = services.AddMvcCore(); + return AddJsonApi(services, opt => { }, mvcBuilder); } public static IServiceCollection AddJsonApi(this IServiceCollection services, Action options) where TContext : DbContext { - var mvcBuilder = services.AddMvc(); + var mvcBuilder = services.AddMvcCore(); return AddJsonApi(services, options, mvcBuilder); } public static IServiceCollection AddJsonApi(this IServiceCollection services, Action options, - IMvcBuilder mvcBuilder) where TContext : DbContext + IMvcCoreBuilder mvcBuilder) where TContext : DbContext { var config = new JsonApiOptions(); @@ -57,7 +57,7 @@ public static IServiceCollection AddJsonApi(this IServiceCollection se public static IServiceCollection AddJsonApi(this IServiceCollection services, Action options, - IMvcBuilder mvcBuilder) + IMvcCoreBuilder mvcBuilder) { var config = new JsonApiOptions(); diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj index 4f52a23002..e9d5eea415 100755 --- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj +++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj @@ -1,6 +1,6 @@  - 2.2.5 + 2.3.0 $(NetStandardVersion) JsonApiDotNetCore JsonApiDotNetCore @@ -17,12 +17,13 @@ - + - + - + + diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomErrorTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomErrorTests.cs index ce2b541f5b..fcc6e5ffde 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomErrorTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomErrorTests.cs @@ -11,7 +11,7 @@ public class CustomErrorTests public void Can_Return_Custom_Error_Types() { // arrange - var error = new CustomError("507", "title", "detail", "custom"); + var error = new CustomError(507, "title", "detail", "custom"); var errorCollection = new ErrorCollection(); errorCollection.Add(error); @@ -36,7 +36,7 @@ public void Can_Return_Custom_Error_Types() } class CustomError : Error { - public CustomError(string status, string title, string detail, string myProp) + public CustomError(int status, string title, string detail, string myProp) : base(status, title, detail) { MyCustomProperty = myProp; diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs index 428e3cadf3..b928df4ada 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs @@ -131,7 +131,7 @@ public async Task Can_Filter_On_Not_Equal_Values() // assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.False(deserializedTodoItems.Any(i => i.Ordinal == todoItem.Ordinal)); + Assert.DoesNotContain(deserializedTodoItems, x => x.Ordinal == todoItem.Ordinal); } [Fact] @@ -170,8 +170,8 @@ public async Task Can_Filter_On_In_Array_Values() Assert.Equal(guids.Count(), deserializedTodoItems.Count()); foreach (var item in deserializedTodoItems) { - Assert.True(guids.Contains(item.GuidProperty)); - Assert.False(notInGuids.Contains(item.GuidProperty)); + Assert.Contains(item.GuidProperty, guids); + Assert.DoesNotContain(item.GuidProperty, notInGuids); } } @@ -207,7 +207,7 @@ public async Task Can_Filter_On_Related_In_Array_Values() Assert.NotNull(included); Assert.NotEmpty(included); foreach (var item in included) - Assert.True(ownerFirstNames.Contains(item.Attributes["first-name"])); + Assert.Contains(item.Attributes["first-name"], ownerFirstNames); } } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs index 343526f7d8..25f81fb66c 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Net; using System.Net.Http; @@ -174,7 +174,7 @@ public async Task GET_Included_DoesNot_Duplicate_Records_ForMultipleRelationship // assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotEmpty(documents.Included); - Assert.Equal(1, documents.Included.Count); + Assert.Single(documents.Included); } [Fact] @@ -209,7 +209,7 @@ public async Task GET_Included_DoesNot_Duplicate_Records_If_HasOne_Exists_Twice( // assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotEmpty(documents.Included); - Assert.Equal(1, documents.Included.Count); + Assert.Single(documents.Included); } [Fact] diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs index faae94a3d8..e50032fce1 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs @@ -1,4 +1,4 @@ -using System.Net; +using System.Net; using System.Net.Http; using System.Threading.Tasks; using JsonApiDotNetCoreExample; @@ -6,7 +6,6 @@ using Microsoft.AspNetCore.TestHost; using Newtonsoft.Json; using Xunit; -using Person = JsonApiDotNetCoreExample.Models.Person; using JsonApiDotNetCore.Models; using JsonApiDotNetCoreExample.Data; using Bogus; @@ -18,28 +17,16 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec.DocumentTests [Collection("WebHostCollection")] public class PagingTests { - private TestFixture _fixture; - private AppDbContext _context; - private Faker _personFaker; - private Faker _todoItemFaker; - private Faker _todoItemCollectionFaker; - private DateTime CurrentTime; + private readonly AppDbContext _context; + private readonly Faker _todoItemFaker; public PagingTests(TestFixture fixture) { - _fixture = fixture; _context = fixture.GetService(); - _personFaker = new Faker() - .RuleFor(p => p.FirstName, f => f.Name.FirstName()) - .RuleFor(p => p.LastName, f => f.Name.LastName()); - _todoItemFaker = new Faker() .RuleFor(t => t.Description, f => f.Lorem.Sentence()) .RuleFor(t => t.Ordinal, f => f.Random.Number()) .RuleFor(t => t.CreatedDate, f => f.Date.Past()); - - _todoItemCollectionFaker = new Faker() - .RuleFor(t => t.Name, f => f.Company.CatchPhrase()); } [Fact] diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs index f5f61e156d..58b2323da5 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs @@ -39,7 +39,7 @@ public async Task Server_Returns_400_ForUnknownQueryParam() // assert Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); - Assert.Equal(1, body.Errors.Count); + Assert.Single(body.Errors); Assert.Equal($"[{queryKey}, {queryValue}] is not a valid query.", body.Errors[0].Title); } } diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs index c774478227..a7bfb95b9d 100644 --- a/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs +++ b/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs @@ -12,38 +12,31 @@ namespace JsonApiDotNetCoreExampleTests.Helpers.Extensions { public static class IQueryableExtensions { - private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo(); - - private static readonly FieldInfo QueryCompilerField = typeof(EntityQueryProvider).GetTypeInfo().DeclaredFields.First(x => x.Name == "_queryCompiler"); + private static readonly FieldInfo QueryCompilerField = typeof(EntityQueryProvider).GetTypeInfo().DeclaredFields.Single(x => x.Name == "_queryCompiler"); - private static readonly PropertyInfo NodeTypeProviderField = QueryCompilerTypeInfo.DeclaredProperties.Single(x => x.Name == "NodeTypeProvider"); + private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo(); - private static readonly MethodInfo CreateQueryParserMethod = QueryCompilerTypeInfo.DeclaredMethods.First(x => x.Name == "CreateQueryParser"); + private static readonly FieldInfo QueryModelGeneratorField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_queryModelGenerator"); - private static readonly FieldInfo DataBaseField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_database"); + private static readonly FieldInfo DatabaseField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_database"); - private static readonly PropertyInfo DatabaseDependenciesField - = typeof(Database).GetTypeInfo().DeclaredProperties.Single(x => x.Name == "Dependencies"); + private static readonly PropertyInfo DependenciesProperty = typeof(Database).GetTypeInfo().DeclaredProperties.Single(x => x.Name == "Dependencies"); - public static string ToSql(this IQueryable query) where TEntity : class + public static string ToSql(this IQueryable queryable) + where TEntity : class { - if (!(query is EntityQueryable) && !(query is InternalDbSet)) - { - throw new ArgumentException("Invalid query"); - } - - var queryCompiler = (IQueryCompiler)QueryCompilerField.GetValue(query.Provider); - var nodeTypeProvider = (INodeTypeProvider)NodeTypeProviderField.GetValue(queryCompiler); - var parser = (IQueryParser)CreateQueryParserMethod.Invoke(queryCompiler, new object[] { nodeTypeProvider }); - var queryModel = parser.GetParsedQuery(query.Expression); - var database = DataBaseField.GetValue(queryCompiler); - var queryCompilationContextFactory = ((DatabaseDependencies)DatabaseDependenciesField.GetValue(database)).QueryCompilationContextFactory; + if (!(queryable is EntityQueryable) && !(queryable is InternalDbSet)) + throw new ArgumentException(); + + var queryCompiler = (IQueryCompiler)QueryCompilerField.GetValue(queryable.Provider); + var queryModelGenerator = (IQueryModelGenerator)QueryModelGeneratorField.GetValue(queryCompiler); + var queryModel = queryModelGenerator.ParseQuery(queryable.Expression); + var database = DatabaseField.GetValue(queryCompiler); + var queryCompilationContextFactory = ((DatabaseDependencies)DependenciesProperty.GetValue(database)).QueryCompilationContextFactory; var queryCompilationContext = queryCompilationContextFactory.Create(false); var modelVisitor = (RelationalQueryModelVisitor)queryCompilationContext.CreateQueryModelVisitor(); modelVisitor.CreateQueryExecutor(queryModel); - var sql = modelVisitor.Queries.First().ToString(); - - return sql; + return modelVisitor.Queries.Join(Environment.NewLine + Environment.NewLine); } } -} \ No newline at end of file +} diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/StringExtensions.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/StringExtensions.cs index 19c7491d2a..dbe6b19feb 100644 --- a/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/StringExtensions.cs +++ b/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/StringExtensions.cs @@ -2,14 +2,14 @@ namespace JsonApiDotNetCoreExampleTests.Helpers.Extensions { - public static class StringExtensions { public static string Normalize(this string input) { return Regex.Replace(input, @"\s+", string.Empty) .ToUpper() - .Replace('"', '\''); + .Replace("\"", string.Empty) + .Replace("'", string.Empty); } } -} \ No newline at end of file +} diff --git a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj index 53f1d4bf77..c0c410f7c7 100755 --- a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj +++ b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj @@ -19,7 +19,7 @@ - + diff --git a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj index 19b8cc61d2..c0500c3bbd 100644 --- a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj +++ b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj @@ -21,7 +21,7 @@ - + diff --git a/test/OperationsExampleTests/Add/AddTests.cs b/test/OperationsExampleTests/Add/AddTests.cs index 39e9e8a2a6..47aba439d6 100644 --- a/test/OperationsExampleTests/Add/AddTests.cs +++ b/test/OperationsExampleTests/Add/AddTests.cs @@ -156,7 +156,7 @@ public async Task Can_Create_Author_With_Article() Assert.Equal(author.Name, lastAuthor.Name); // article validation - Assert.Equal(1, lastAuthor.Articles.Count); + Assert.Single(lastAuthor.Articles); Assert.Equal(article.Name, lastAuthor.Articles[0].Name); Assert.Equal(articleOperationResult.DataObject.Id, lastAuthor.Articles[0].StringId); } diff --git a/test/OperationsExampleTests/Get/GetByIdTests.cs b/test/OperationsExampleTests/Get/GetByIdTests.cs index 1dee2867ce..1056082895 100644 --- a/test/OperationsExampleTests/Get/GetByIdTests.cs +++ b/test/OperationsExampleTests/Get/GetByIdTests.cs @@ -36,14 +36,14 @@ public async Task Can_Get_Author_By_Id() }; // act - var result = await PatchAsync("api/bulk", content); + var (response, data) = await PatchAsync("api/bulk", content); // assert - Assert.NotNull(result.response); - Assert.NotNull(result.data); - Assert.Equal(HttpStatusCode.OK, result.response.StatusCode); - Assert.Equal(1, result.data.Operations.Count); - Assert.Equal(author.Id.ToString(), result.data.Operations.Single().DataObject.Id); + Assert.NotNull(response); + Assert.NotNull(data); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Single(data.Operations); + Assert.Equal(author.Id.ToString(), data.Operations.Single().DataObject.Id); } [Fact] @@ -69,7 +69,7 @@ public async Task Get_Author_By_Id_Returns_404_If_NotFound() Assert.NotNull(response); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); Assert.NotNull(data); - Assert.Equal(1, data.Errors.Count); + Assert.Single(data.Errors); Assert.True(data.Errors[0].Detail.Contains("authors"), "The error detail should contain the name of the entity that could not be found."); Assert.True(data.Errors[0].Detail.Contains(authorId), "The error detail should contain the entity id that could not be found"); Assert.True(data.Errors[0].Title.Contains("operation[0]"), "The error title should contain the operation identifier that failed"); diff --git a/test/OperationsExampleTests/Get/GetRelationshipTests.cs b/test/OperationsExampleTests/Get/GetRelationshipTests.cs index 03f276da17..8599e92a1e 100644 --- a/test/OperationsExampleTests/Get/GetRelationshipTests.cs +++ b/test/OperationsExampleTests/Get/GetRelationshipTests.cs @@ -43,7 +43,7 @@ public async Task Can_Get_Article_Author() Assert.NotNull(response); Assert.NotNull(data); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal(1, data.Operations.Count); + Assert.Single(data.Operations); var resourceObject = data.Operations.Single().DataObject; Assert.Equal(author.Id.ToString(), resourceObject.Id); Assert.Equal("authors", resourceObject.Type); diff --git a/test/OperationsExampleTests/Get/GetTests.cs b/test/OperationsExampleTests/Get/GetTests.cs index bf1c15e3a4..78e7eeb976 100644 --- a/test/OperationsExampleTests/Get/GetTests.cs +++ b/test/OperationsExampleTests/Get/GetTests.cs @@ -44,7 +44,7 @@ public async Task Can_Get_Authors() Assert.NotNull(result.response); Assert.NotNull(result.data); Assert.Equal(HttpStatusCode.OK, result.response.StatusCode); - Assert.Equal(1, result.data.Operations.Count); + Assert.Single(result.data.Operations); Assert.Equal(expectedCount, result.data.Operations.Single().DataList.Count); } } diff --git a/test/OperationsExampleTests/OperationsExampleTests.csproj b/test/OperationsExampleTests/OperationsExampleTests.csproj index 3b866d4207..c2c70d6e54 100644 --- a/test/OperationsExampleTests/OperationsExampleTests.csproj +++ b/test/OperationsExampleTests/OperationsExampleTests.csproj @@ -10,7 +10,7 @@ - + diff --git a/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs b/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs index 05dea7f29d..191711651d 100644 --- a/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs +++ b/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs @@ -68,7 +68,7 @@ public async Task Cannot_Create_Author_If_Article_Creation_Fails() // for now, it is up to application implementations to perform validation and // provide the proper HTTP response code Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); - Assert.Equal(1, data.Errors.Count); + Assert.Single(data.Errors); Assert.Contains("operation[1] (add)", data.Errors[0].Title); var dbAuthors = await context.Authors.Where(a => a.Name == author.Name).ToListAsync(); diff --git a/test/OperationsExampleTests/Update/UpdateTests.cs b/test/OperationsExampleTests/Update/UpdateTests.cs index c5d0f20900..c5d220b2f5 100644 --- a/test/OperationsExampleTests/Update/UpdateTests.cs +++ b/test/OperationsExampleTests/Update/UpdateTests.cs @@ -52,7 +52,7 @@ public async Task Can_Update_Author() Assert.NotNull(response); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(data); - Assert.Equal(1, data.Operations.Count); + Assert.Single(data.Operations); var attrs = data.Operations.Single().DataObject.Attributes; Assert.Equal(updates.Name, attrs["name"]); diff --git a/test/UnitTests/Builders/DocumentBuilder_Tests.cs b/test/UnitTests/Builders/DocumentBuilder_Tests.cs index fc816765eb..84c1f3f5c7 100644 --- a/test/UnitTests/Builders/DocumentBuilder_Tests.cs +++ b/test/UnitTests/Builders/DocumentBuilder_Tests.cs @@ -190,7 +190,7 @@ public void Build_Can_Build_Arrays() var documents = documentBuilder.Build(entities); - Assert.Equal(1, documents.Data.Count); + Assert.Single(documents.Data); } [Fact] @@ -201,7 +201,7 @@ public void Build_Can_Build_CustomIEnumerables() var documents = documentBuilder.Build(entities); - Assert.Equal(1, documents.Data.Count); + Assert.Single(documents.Data); } diff --git a/test/UnitTests/Controllers/JsonApiControllerMixin_Tests.cs b/test/UnitTests/Controllers/JsonApiControllerMixin_Tests.cs index a18aeaf668..c7a4a6cb4d 100644 --- a/test/UnitTests/Controllers/JsonApiControllerMixin_Tests.cs +++ b/test/UnitTests/Controllers/JsonApiControllerMixin_Tests.cs @@ -16,26 +16,26 @@ public void Errors_Correctly_Infers_Status_Code() // arrange var errors422 = new ErrorCollection { Errors = new List { - new Error("422", "bad specific"), - new Error("422", "bad other specific"), + new Error(422, "bad specific"), + new Error(422, "bad other specific"), } }; var errors400 = new ErrorCollection { Errors = new List { - new Error("200", "weird"), - new Error("400", "bad"), - new Error("422", "bad specific"), + new Error(200, "weird"), + new Error(400, "bad"), + new Error(422, "bad specific"), } }; var errors500 = new ErrorCollection { Errors = new List { - new Error("200", "weird"), - new Error("400", "bad"), - new Error("422", "bad specific"), - new Error("500", "really bad"), - new Error("502", "really bad specific"), + new Error(200, "weird"), + new Error(400, "bad"), + new Error(422, "bad specific"), + new Error(500, "really bad"), + new Error(502, "really bad specific"), } }; diff --git a/test/UnitTests/Internal/ContextGraphBuilder_Tests.cs b/test/UnitTests/Internal/ContextGraphBuilder_Tests.cs index ce8316b89d..5f56ac0bd8 100644 --- a/test/UnitTests/Internal/ContextGraphBuilder_Tests.cs +++ b/test/UnitTests/Internal/ContextGraphBuilder_Tests.cs @@ -33,7 +33,7 @@ public void Adding_DbContext_Members_That_DoNot_Implement_IIdentifiable_Creates_ var contextGraph = contextGraphBuilder.Build() as ContextGraph; // assert - Assert.Equal(1, contextGraph.ValidationResults.Count); + Assert.Single(contextGraph.ValidationResults); Assert.Contains(contextGraph.ValidationResults, v => v.LogLevel == LogLevel.Warning); } diff --git a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs index ec34d87d24..be16d1d9d7 100644 --- a/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs +++ b/test/UnitTests/Serialization/JsonApiDeSerializerTests.cs @@ -181,7 +181,7 @@ public void Immutable_Attrs_Are_Not_Included_In_AttributesToUpdate() // assert Assert.NotNull(result.ComplexMember); - Assert.Equal(1, attributesToUpdate.Count); + Assert.Single(attributesToUpdate); foreach (var attr in attributesToUpdate) Assert.False(attr.Key.IsImmutable); diff --git a/test/UnitTests/UnitTests.csproj b/test/UnitTests/UnitTests.csproj index 39132d0b0a..f8dde36f41 100644 --- a/test/UnitTests/UnitTests.csproj +++ b/test/UnitTests/UnitTests.csproj @@ -9,7 +9,7 @@ - +