簡體   English   中英

EntityFrameworkCore 查詢數據時拋出 NullReferenceException

[英]EntityFrameworkCore throws NullReferenceException when querying data

我正在使用 EF Core 2.2 連接到 Oracle11g 數據庫(必須使用這些舊版本),當我嘗試查詢我的一個表時,它會在 EF Core 外部代碼中引發NullReferenceException 查詢:

string username = "Administrator";
var user = _context.Users.Where(x => x.UserName.ToUpper() == username.ToUpper())
                    .Include(x => x.UserProfile)
                    .Include(x => x.UserRoleOrganizations).ThenInclude(s => s.Role)
                    .Include(x => x.UserRoleOrganizations).ThenInclude(s => s.Organization);

return user.FirstOrDefault();

例外:

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=Microsoft.EntityFrameworkCore.Relational
  StackTrace:
   at Microsoft.EntityFrameworkCore.Storage.TypedRelationalValueBufferFactoryFactory.CreateGetValueExpression(Expression dataReaderExpression, Int32 index, TypeMaterializationInfo materializationInfo, Boolean detailedErrorsEnabled, Boolean box)
   at Microsoft.EntityFrameworkCore.Storage.TypedRelationalValueBufferFactoryFactory.<>c__DisplayClass13_0.<CreateArrayInitializer>b__0(TypeMaterializationInfo mi, Int32 i)
   at System.Linq.Enumerable.<SelectIterator>d__5`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Dynamic.Utils.CollectionExtensions.ToReadOnly[T](IEnumerable`1 enumerable)
   at System.Linq.Expressions.Expression.NewArrayInit(Type type, IEnumerable`1 initializers)
   at Microsoft.EntityFrameworkCore.Storage.TypedRelationalValueBufferFactoryFactory.CreateArrayInitializer(CacheKey cacheKey, Boolean detailedErrorsEnabled)
   at Microsoft.EntityFrameworkCore.Storage.TypedRelationalValueBufferFactoryFactory.<Create>b__11_0(CacheKey k)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam,TValue](TValue& target, TParam param, Func`2 valueFactory)
   at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.NotifyReaderCreated(DbDataReader dataReader)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer)
   at Oracle.EntityFrameworkCore.Storage.Internal.OracleExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ResultEnumerable`1.GetEnumerator()
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.<_TrackEntities>d__17`2.MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass15_1`1.<CompileQueryCore>b__0(QueryContext qc)
   at Base.Security.Business.UserManagement.GetUser(String username) in C:\Users\Afagh2\source\repos\HSE2_Oracle\Base.Security\Business\UserManagement.cs:line 88

生成的查詢:

[Parameters=[:ToUpper_0='ADMINISTRATOR' (Size = 256)], CommandType='Text', CommandTimeout='0']
Select
K0 "Id", K1 "AccessFailedCount", K2 "ConcurrencyStamp", K3 "Email", K4 "EmailConfirmed", K5 "FirstName", K6 "IsActive", K7 "IsExternal", K8 "LastName", K9 "LockoutEnabled", K10 "LockoutEnd", K11 "NationalCode", K12 "NormalizedEmail", K13 "NormalizedUserName", K14 "OrganizationName", K15 "OrganizationType", K16 "PasswordHash", K17 "PersonnelCode", K18 "PhoneNumber", K19 "PhoneNumberConfirmed", K20 "PositionName", K21 "SecurityStamp", K22 "TwoFactorEnabled", K23 "UserName", K24 "Id", K25 "FileContent", K26 "FileExtension", K27 "FileName" from(
  SELECT "x"."Id" K0, "x"."AccessFailedCount" K1, "x"."ConcurrencyStamp" K2, "x"."Email" K3, "x"."EmailConfirmed" K4, "x"."FirstName" K5, "x"."IsActive" K6, "x"."IsExternal" K7, "x"."LastName" K8, "x"."LockoutEnabled" K9, "x"."LockoutEnd" K10, "x"."NationalCode" K11, "x"."NormalizedEmail" K12, "x"."NormalizedUserName" K13, "x"."OrganizationName" K14, "x"."OrganizationType" K15, "x"."PasswordHash" K16, "x"."PersonnelCode" K17, "x"."PhoneNumber" K18, "x"."PhoneNumberConfirmed" K19, "x"."PositionName" K20, "x"."SecurityStamp" K21, "x"."TwoFactorEnabled" K22, "x"."UserName" K23, "x.UserProfile"."Id" K24, "x.UserProfile"."FileContent" K25, "x.UserProfile"."FileExtension" K26, "x.UserProfile"."FileName" K27
  FROM "AppUser" "x"
  LEFT JOIN "AppUserProfilePicture" "x.UserProfile" ON ("x"."Id" = "x.UserProfile"."Id")
  WHERE ("UPPER"("x"."UserName") = :ToUpper_0)
  ORDER BY "x"."Id"
) "m1"
where rownum <= 1

該查詢在 Oracle SQL Developer 中按預期工作。 似乎 EF Core 在將結果轉換為實體時遇到了一些麻煩(在這種情況下,結果應該是 none,因為表沒有數據。)但我無法調試它的代碼。 (或者我可以嗎?)
實體在OnModelCreating中配置:

builder.Entity<ApplicationUser>(b =>
{
    b.HasKey(u => u.Id);
    b.HasIndex(u => u.NormalizedUserName).HasName("UserNameIndex").IsUnique();
    b.HasIndex(u => u.NormalizedEmail).HasName("EmailIndex");
    b.ToTable("AppUser");
    b.Property(u => u.ConcurrencyStamp).IsConcurrencyToken();

    b.Property(u => u.UserName).HasMaxLength(256);
    b.Property(u => u.NormalizedUserName).HasMaxLength(256);
    b.Property(u => u.Email).HasMaxLength(256);
    b.Property(u => u.NormalizedEmail).HasMaxLength(256);

    b.HasOne(x => x.UserProfile).WithOne(x => x.User).HasForeignKey<ApplicationUserProfilePicture>(x => x.Id);
    b.HasMany<IdentityUserClaim<int>>().WithOne().HasForeignKey(uc => uc.UserId).IsRequired();
    b.HasMany<IdentityUserLogin<int>>().WithOne().HasForeignKey(ul => ul.UserId).IsRequired();
    b.HasMany<IdentityUserToken<int>>().WithOne().HasForeignKey(ut => ut.UserId).IsRequired();
    b.HasMany<ApplicationUserRoleOrganization>().WithOne().HasForeignKey(ur => ur.UserId).IsRequired();
});

我可以創建和查詢其他表。 只有AppUser表在 Oracle 中不起作用,使用 SQL 服務器提供程序可以正常工作。 告訴我是否需要有關任何內容的更多信息。


更新
用戶 class:

public class ApplicationUser : Microsoft.AspNetCore.Identity.IdentityUser<int>
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    [StringLength(450)]
    public string PositionName { get; set; }
    [StringLength(450)]
    public string NationalCode { get; set; }
    [StringLength(450)]
    public string PersonnelCode { get; set; }
    public bool IsActive { get; set; } = true;
    public bool IsExternal { get; set; } = false;
    [Required]
    public OrganizationTypeEnum OrganizationType { get; set; }
    public string OrganizationName { get; set; }
    public virtual ApplicationUserProfilePicture UserProfile { get; set; }
    public virtual ICollection<ApplicationUserRoleOrganization> UserRoleOrganizations { get; set; }
}

用戶角色組織 class:

public class ApplicationUserRoleOrganization : Microsoft.AspNetCore.Identity.IdentityUserRole<int>
{
    public int Id { get; set; }
    public override int RoleId { get => base.RoleId; set => base.RoleId = value; }
    public override int UserId { get => base.UserId; set => base.UserId = value; }
    public virtual int OrganizationId { get; set; }
    public virtual ApplicationUser User { get; set; }
    public virtual ApplicationRole Role { get; set; }
    public virtual Organization Organization { get; set; }
}

UserRoleOrganization 的配置:

builder.Entity<ApplicationUserRoleOrganization>(b =>
{
    b.HasKey(r => r.Id);
    b.HasIndex(t => t.OrganizationId).HasName("OrganizationIndex");
    b.HasIndex(t => t.RoleId).HasName("RoleIndex");
    b.HasIndex(t => t.UserId).HasName("UserIndex");
    b.HasOne(userRole => userRole.Role)
    .WithMany(role => role.UserRoleOrganizations)
    .HasForeignKey(userRole => userRole.RoleId).HasConstraintName("FK_RoleOrg_Role_RoleId");
    b.HasOne(userRole => userRole.Organization)
    .WithMany(role => role.UserRoleOrganizations)
    .HasForeignKey(userRole => userRole.OrganizationId).HasConstraintName("FK_RoleOrg_Org_OrgId");
    b.HasOne(userRole => userRole.User)
    .WithMany(user => user.UserRoleOrganizations)
    .HasForeignKey(userRole => userRole.UserId).HasConstraintName("FK_RoleOrg_User_UserId");
    b.ToTable("AppUserRoleOrganization");
});

我剛剛注意到在異常之前在我的 output 中寫了一條文本:

fail: Microsoft.EntityFrameworkCore.Query[10100]
      An exception occurred while iterating over the results of a query for context type 'Base.Security.Data.SecurityDbContext'.

您已包含 UserRoleOrganizations 兩次。 嘗試做包括好的舊方法:

string username = "Administrator";
return _context.Users.Where(x => x.UserName.ToUpper() == username.ToUpper())
                    .Include(x => x.UserProfile)
                    .Include("UserRoleOrganizations.Organization");
                    .Include("UserRoleOrganizations.Role")
                    .FirstOrDefault();

但我不喜歡 UserRoleOrganizations.Organization。 您能否展示您的 User 和 UserRoleOrganizations 類?

更新。

由於我可以看到這些類,我認為您可以嘗試反向查詢,也許只是為了測試:


var userRoleOrganizations=_context.UserRoleOrganizations
.Where(x => x.User.UserName.ToUpper() == username.ToUpper())
.Include(s => s.Role)
.Include(s => s.Organization)
.ToList();

var user = _context.Users
.Where(x => x.UserName.ToUpper() == username.ToUpper())
.Include(x => x.UserProfile)
.FirstOrDefault();

user.UserRoleOrganizations=userRoleOrganizations;

return user;

並嘗試更改 UserRoleOrganizations class:

public class UserRoleOrganizations
{
....
public  override int? RoleId { get => base.RoleId; set => base.RoleId = value; }
 public override int? UserId { get => base.UserId; set => base.UserId = value; }
 public virtual int? OrganizationId { get; set; }
....
}
   

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM