question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Failed to get resource with relationships when using Entity Framework Core Sqlite

See original GitHub issue

DESCRIPTION

I tried to get the resource by id with including relationship but I got http status code 500 (Internal Server Error). The response I got is : { "errors": [ { "id": "06690e41-98f5-4f48-abaf-378434496c74", "status": "500", "title": "An unhandled error occurred while processing this request.", "detail": "SQLite Error 1: 'near \"(\": syntax error'.", "meta": { "stackTrace": [ "Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'near \"(\": syntax error'.\r", " at void Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(int rc, sqlite3 db)\r", " at IEnumerable<sqlite3_stmt> Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements(Stopwatch timer)+MoveNext()\r", " at IEnumerable<sqlite3_stmt> Microsoft.Data.Sqlite.SqliteCommand.GetStatements(Stopwatch timer)+MoveNext()\r", " at bool Microsoft.Data.Sqlite.SqliteDataReader.NextResult()\r", " at SqliteDataReader Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior)\r", " at Task<SqliteDataReader> Microsoft.Data.Sqlite.SqliteCommand.ExecuteReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)\r", " at async Task<DbDataReader> Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)\r", " at async Task<RelationalDataReader> Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)\r", " at async Task<RelationalDataReader> Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)\r", " at async Task<RelationalDataReader> Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)\r", " at async Task<bool> Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable<T>+AsyncEnumerator.InitializeReaderAsync(DbContext _, bool result, CancellationToken cancellationToken)\r", " at async ValueTask<bool> Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable<T>+AsyncEnumerator.MoveNextAsync()\r", " at async Task<List<TSource>> Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync<TSource>(IQueryable<TSource> source, CancellationToken cancellationToken)\r", " at async Task<List<TSource>> Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync<TSource>(IQueryable<TSource> source, CancellationToken cancellationToken)\r", " at async Task<IReadOnlyCollection<TResource>> JsonApiDotNetCore.Repositories.EntityFrameworkCoreRepository<TResource, TId>.GetAsync(QueryLayer layer, CancellationToken cancellationToken) in C:/Users/admin/Downloads/JsonApiDotNetCore-master (1)/JsonApiDotNetCore-master/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs:line 62\r", " at object CallSite.Target(Closure, CallSite, object)\r", " at TRet System.Dynamic.UpdateDelegates.UpdateAndExecute1<T0, TRet>(CallSite site, T0 arg0)\r", " at async Task<IReadOnlyCollection<TResource>> JsonApiDotNetCore.Repositories.ResourceRepositoryAccessor.GetAsync<TResource>(QueryLayer layer, CancellationToken cancellationToken) in C:/Users/admin/Downloads/JsonApiDotNetCore-master (1)/JsonApiDotNetCore-master/src/JsonApiDotNetCore/Repositories/ResourceRepositoryAccessor.cs:line 30\r", " at async Task<TResource> JsonApiDotNetCore.Services.JsonApiResourceService<TResource, TId>.TryGetPrimaryResourceByIdAsync(TId id, TopFieldSelection fieldSelection, CancellationToken cancellationToken) in C:/Users/admin/Downloads/JsonApiDotNetCore-master (1)/JsonApiDotNetCore-master/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs:line 423\r", " at async Task<TResource> JsonApiDotNetCore.Services.JsonApiResourceService<TResource, TId>.GetAsync(TId id, CancellationToken cancellationToken) in C:/Users/admin/Downloads/JsonApiDotNetCore-master (1)/JsonApiDotNetCore-master/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs:line 94\r", " at async Task<IActionResult> JsonApiDotNetCore.Controllers.BaseJsonApiController<TResource, TId>.GetAsync(TId id, CancellationToken cancellationToken) in C:/Users/admin/Downloads/JsonApiDotNetCore-master (1)/JsonApiDotNetCore-master/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs:line 114\r", " at async Task<IActionResult> JsonApiDotNetCore.Controllers.JsonApiController<TResource, TId>.GetAsync(TId id, CancellationToken cancellationToken) in C:/Users/admin/Downloads/JsonApiDotNetCore-master (1)/JsonApiDotNetCore-master/src/JsonApiDotNetCore/Controllers/JsonApiController.cs:line 58\r", " at async ValueTask<IActionResult> Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)\r", " at TResult System.Runtime.CompilerServices.ValueTaskAwaiter<TResult>.GetResult()\r", " at async Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()+Awaited(?)\r", " at async Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()+Awaited(?)\r", " at void Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)\r", " at Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)\r", " at Task Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()\r", " at async Task Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextExceptionFilterAsync()+Awaited(?)" ] } } ] }

I tried with the latest JsonApiDotnetCore and Entity Framework Core Sqlite.

STEPS TO REPRODUCE

Models:

public class Role : Identifiable
    {
        [Attr]
        public string Name { get; set; }

        [Attr]
        public string Description { get; set; }
    }

public class Group : Identifiable
    {
        [Attr]
        public string GroupName { get; set; }

        [Attr]
        public string Description { get; set; }

        [HasMany]
        public ICollection<Role> Roles { get; set; }
    }

DbContext:

public class SqliteAppDbContext : DbContext
    {
        public ISystemClock SystemClock { get; }

        public DbSet<Group> Groups { get; set; }
        public DbSet<Role> Roles { get; set; }

        public SqliteAppDbContext(DbContextOptions<SqliteAppDbContext> options, ISystemClock systemClock) : base(options)
        {
            SystemClock = systemClock ?? throw new ArgumentNullException(nameof(systemClock));
        }        
    }

Startup:

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public virtual void ConfigureServices(IServiceCollection services)
        {
            //options.UseLoggerFactory(this.LoggerFactory);
            services.AddSingleton<ISystemClock, SystemClock>();
            //services.AddControllers();
            //var testDb = Guid.NewGuid().ToString();
            var connection = new SqliteConnection("DataSource=sqlitedemo.db");
            connection.Open();
            services.AddSingleton(connection);

            services.AddDbContext<SqliteAppDbContext>(options =>
            {
                options.UseSqlite(connection);
                //options.UseLoggerFactory(loggerFactory);
                options.EnableDetailedErrors();
                options.EnableSensitiveDataLogging();
            });
            services.AddJsonApi<SqliteAppDbContext>(ConfigureJsonApiOptions, discovery => discovery.AddCurrentAssembly());

            services.AddClientSerialization();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();
            app.UseJsonApi();
            app.UseEndpoints(endpoints => endpoints.MapControllers());
        }

        protected virtual void ConfigureJsonApiOptions(JsonApiOptions options)
        {
            options.IncludeExceptionStackTraceInErrors = true;
            options.Namespace = "api/v1";
            options.DefaultPageSize = new PageSize(5);
            options.IncludeTotalResourceCount = true;
            options.ValidateModelState = true;
            options.SerializerSettings.Formatting = Formatting.Indented;
            options.SerializerSettings.Converters.Add(new StringEnumConverter());
        }
    }

The sql script was generated when queried the group:

Executing DbCommand [Parameters=[@__Create_Item1_1='5' (DbType = String), @__Create_Item1_0='1' (DbType = String)], CommandType='Text', CommandTimeout='30']
      SELECT "g"."Id", "g"."Description", "g"."GroupName", "t"."Id", "t"."Description", "t"."GroupId", "t"."Name"
      FROM "Groups" AS "g"
      OUTER APPLY (
          SELECT "r"."Id", "r"."Description", "r"."GroupId", "r"."Name"
          FROM "Roles" AS "r"
          WHERE "g"."Id" = "r"."GroupId"
          ORDER BY "r"."Id"
          LIMIT @__Create_Item1_1
      ) AS "t"
      WHERE "g"."Id" = @__Create_Item1_0
      ORDER BY "g"."Id", "t"."Id"

Query:

  • Http method: GET
  • Url: api/v1/groups/1?include=roles

EXPECTED BEHAVIOR

Can get the group (id=1) with its roles.

ACTUAL BEHAVIOR

Error with “SQLite Error 1: ‘near "(": syntax error’.”

VERSIONS USED

  • JsonApiDotNetCore version: 4.0.1
  • ASP.NET Core version: 3.1.0
  • Entity Framework Core version: 3.1.10
  • Entity Framework Core Sqlite version: 3.1.10
  • Database provider: Sqlite

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
bart-degreedcommented, Jan 11, 2021

It worked in JADNC v4-alpha5 because it did not provide nested paging. In #792 (released in v4-beta1), we redesigned the way LINQ expressions are built, to fix bugs and enable various new features. For example, in alpha5 a request like /blogs/1/articles would always return all related articles, which is unacceptable for large tables in production scenarios.

I’m going to leave this issue open to remind myself to create a ‘known limitations’ issue that I can reference to in future reports.

0reactions
bart-degreedcommented, Jan 13, 2021

Created #922, which contains another workaround.

Read more comments on GitHub >

github_iconTop Results From Across the Web

EF Core / Sqlite one-to-many relationship failing on Unique ...
The problem is that Add method cascades: Begins tracking the given entity, and any other reachable entities that are not already being ...
Read more >
Breaking changes in EF Core 7.0 (EF7)
Complete list of breaking changes introduced in Entity Framework Core 7.0 (EF7)
Read more >
Breaking changes in EF Core 6.0
Complete list of breaking changes introduced in Entity Framework Core 6.0.
Read more >
Troubleshooting Core Data
Explains how to manage objects using the Core Data framework. ... The deletion failed to break all relationships from other objects to the ......
Read more >
Migrations and Seed Data With Entity Framework Core
We are going to learn about Migrations and Seed data in Entity Framework Core and how to optimize EF Core migrations.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found