Skip to content

The UpdateAsync method of the DbSet object does not work with the error: Object reference not set to an instance of an object. #831

@LEIRONGHUA

Description

@LEIRONGHUA

Describe the bug

My project referenced https://github.com/dotnetcore/sharding-core after
Using the EntityFramework-Plus method (e.g., BulkMergeAsync, UpdateAsync) on the DbSet object does not work,
System.NullReferenceException: Object reference not set to an instance of an object.

Version used
9.103.9.2

Code snippet

var dbSet = await _lineClassDayRepository.GetDbSetAsync();
await dbSet.Where(p => p.ClassDate == DateTime.Now.Date).UpdateAsync(x => new LineClassDay()
{
    Remark = "Test Remark:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
});

Logs

System.NullReferenceException: Object reference not set to an instance of an object.

System.NullReferenceException
Object reference not set to an instance of an object.
   at .[](IQueryable`1 , String )
   at Z.EntityFramework.Extensions.BatchUpdate.Execute[T](IQueryable`1 query, Expression`1 updateFactory)
   at BatchUpdateExtensions.UpdateFromQuery[T](IQueryable`1 query, Expression`1 updateFactory, Action`1 batchUpdateBuilder)
   at Z.EntityFramework.Plus.BatchUpdateExtensions.Update[T](IQueryable`1 query, Expression`1 updateFactory, Action`1 batchUpdateBuilder)
   at Z.EntityFramework.Plus.BatchUpdateExtensions.<>c__DisplayClass8_0`1.<UpdateAsync>b__0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
   at Cyw.MyAbp.CustomClass.EntityFrameworkCore.Repositories.EfCoreLineClassDayRepository_Tests.BulkMergeAsync()
   at Xunit.Sdk.TestInvoker`1.<>c__DisplayClass47_0.<<InvokeTestMethodAsync>b__1>d.MoveNext() in /_/src/xunit.execution/Sdk/Frameworks/Runners/TestInvoker.cs:line 259
--- End of stack trace from previous location ---
   at Xunit.Sdk.ExecutionTimer.AggregateAsync(Func`1 asyncAction) in /_/src/xunit.execution/Sdk/Frameworks/ExecutionTimer.cs:line 48
   at Xunit.Sdk.ExceptionAggregator.RunAsync(Func`1 code) in /_/src/xunit.core/Sdk/ExceptionAggregator.cs:line 90

Cause

can't get the QueryContextFactory here because the queryCompiler is of type ShardingCore.EFCores.ShardingQueryCompiler but the QueryContextFactory is in the parent class

QueryCompiler queryCompiler = (QueryCompiler)typeof(EntityQueryProvider)
            .GetField("_queryCompiler", BindingFlags.Instance | BindingFlags.NonPublic)
            .GetValue((object)dbSet.AsQueryable().Provider);
object obj1 = queryCompiler.GetType()
            .GetField("_queryContextFactory", BindingFlags.Instance | BindingFlags.NonPublic) // TODO: Here is null
            .GetValue((object)queryCompiler);
Image

Suggestion

Start with the current type in a loop, step by step to find the _queryContextFactory field of the parent class until you find it

object GetQueryContextFactory(QueryCompiler queryCompiler)
{
    var type = queryCompiler.GetType();
    while (type != null)
    {
        var field = type.GetField("_queryContextFactory", BindingFlags.Instance | BindingFlags.NonPublic);
        if (field != null)
        {
            return field.GetValue(queryCompiler);
        }
        type = type.BaseType;
    }
    return null;
}

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions