21

I don't know what this error means. I am using Visual Studio for Mac 7.5.0 Community version. I am using lazy loading in Entity Framework with ASP.NET Core.

public partial class AdminUser
{
    public AdminUser()
    {
        RoleAssign = new HashSet<RoleAssign>();
    }

    public Guid UserId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string UserName { get; set; }
    public byte[] Password { get; set; }
    public DateTime CreatedTimeStamp { get; set; }
    public DateTime? ModifiedTimeStamp { get; set; }
    public DateTime? LogDate { get; set; }
    public short? LogNumber { get; set; }
    public bool ReloadActiveFlag { get; set; }
    public bool IsActive { get; set; }
    public string ExtraText { get; set; }
    public string ResetPasswordToken { get; set; }
    public DateTime? ResetPasswordTokenCreatedTimeStamp { get; set; }

    public virtual ICollection<RoleAssign> RoleAssign { get; set; }
}

RoleAssign Entity Model:

public partial class RoleAssign
{
    public Guid RoleAssignId { get; set; }
    public Guid RoleId { get; set; }
    public Guid UserId { get; set; }

    public virtual AdminRole Role { get; set; }
    public virtual AdminUser User { get; set; }
}

Here is the entity builder:

modelBuilder.Entity<RoleAssign>(entity =>
{
    entity.Property(e => e.RoleAssignId).ValueGeneratedNever();

    entity.HasOne(d => d.Role)
        .WithMany(p => p.RoleAssign)
        .HasForeignKey(d => d.RoleId)
        .OnDelete(DeleteBehavior.ClientSetNull)
        .HasConstraintName("FK__RoleAssig__RoleI__160F4887");

    entity.HasOne(d => d.User)
        .WithMany(p => p.RoleAssign)
        .HasForeignKey(d => d.UserId)
        .OnDelete(DeleteBehavior.ClientSetNull)
        .HasConstraintName("FK__RoleAssig__UserI__17036CC0");
});

Here is the entity builder for user table:

modelBuilder.Entity<AdminUser>(entity =>
{
    entity.HasKey(e => e.UserId);

    entity.Property(e => e.UserId).ValueGeneratedNever();

    entity.Property(e => e.CreatedTimeStamp)
        .HasColumnType("datetime")
        .HasDefaultValueSql("(getdate())");

    entity.Property(e => e.Email)
        .IsRequired()
        .IsUnicode(false);

    entity.Property(e => e.ExtraText).IsUnicode(false);

    entity.Property(e => e.FirstName)
        .IsRequired()
        .IsUnicode(false);

    entity.Property(e => e.IsActive)
        .IsRequired()
        .HasColumnName("isActive")
        .HasDefaultValueSql("((1))");

    entity.Property(e => e.LastName)
        .IsRequired()
        .IsUnicode(false);

    entity.Property(e => e.LogDate).HasColumnType("datetime");

    entity.Property(e => e.ModifiedTimeStamp).HasColumnType("datetime");

    entity.Property(e => e.Password).IsRequired();

    entity.Property(e => e.ResetPasswordToken).IsUnicode(false);

    entity.Property(e => e.ResetPasswordTokenCreatedTimeStamp).HasColumnType("datetime");

    entity.Property(e => e.UserName)
        .IsRequired()
        .IsUnicode(false);
});

UOW Code:

public async Task<UserViewModel> AdminAuthentication(UserViewModel userView)
{
    var user = await _adminGenericRepository.FindAsync(x => x.IsActive && x.UserName.Equals(userView.UserName) && (AesEncryptAndDecrypt.DecryptStringFromBytes(x.Password, crytograpyKey, crytograpyIV).Equals(userView.Password)));

    if (user != null)
    {
        return new UserViewModel
        {
            UserId = user.UserId,
            isActive = user.IsActive,
            UserName = user.UserName,
            LastName = user.LastName,
            FirstName = user.FirstName,
            SelectedRole = mapRoleDbDataToViewModel(user.RoleAssign != null ? user.RoleAssign.FirstOrDefault().Role : null)
        };
    }
    return null;
}

Mapper Class:

private RoleViewModel mapRoleDbDataToViewModel(AdminRole dbRole)
{
    if (dbRole != null)
    {
        return new RoleViewModel
        {
            RoleId = dbRole.RoleId,
            RoleName = dbRole.RoleName,
            RoleType = dbRole.RoleType,
            SortOrder = dbRole.SortOrder,
            TreeLevel = dbRole.TreeLevel,
            Permissions = GetRuleByRoleId(dbRole.RoleId)
        };
    }
    return null;
}

Repository file:

public virtual async Task<T> FindAsync(Expression<Func<T, bool>> predicate)
{
    return await _entities.Set<T>().SingleOrDefaultAsync(predicate);
}

public IQueryable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
    IQueryable<T> query = _entities.Set<T>().Where(predicate);
    return query;
}

Screenshot of the error message:

error image

Transcript:

Inspecting the state of an object in the debuggee of type System.Reflection.MethodBase is not supported in this context.

Marc.2377
  • 5,840
  • 5
  • 43
  • 75
San Jaisy
  • 9,586
  • 15
  • 93
  • 162
  • Is this error stopping the code from executing? – Nkosi Aug 26 '18 at 23:46
  • yes. Code doesn't execute after that.. – San Jaisy Aug 26 '18 at 23:48
  • Please add the code for `_adminGenericRepository.FindAsync()`, as well as the whole code line from the breakpoint in the image: `var user = await ....` When left to run without the breakpoint, what exception is raised? – Steve Py Aug 27 '18 at 05:35
  • add full code. Getting error on SelectedRole = mapRoleDbDataToViewModel(user.RoleAssign != null ? user.RoleAssign.FirstOrDefault().Role : null) . Due to that error – San Jaisy Aug 27 '18 at 10:07
  • @StevePy - I found that --> Lazy Loading doesn't fit well with the Async pattern. Can you have any idea related to this issue – San Jaisy Aug 28 '18 at 12:16

2 Answers2

5

From what i understood you where debugging and this occurred which is produced from the Visual Studio debugger's expression elevator so it may means that the debugger was trying to fetch data from an instance that is of type System.Reflection.MethodBase but such object was not available so it produced that error ,

you can try using the legacy debug engine,might fix it (Tools -> Options -> Debugging -> General -> "Use Managed Compatibility Mode")

Wesam
  • 848
  • 3
  • 15
  • 27
  • I am using visual studio for mac. I don't find that option as you said. I tried to find that option but haven't found. – San Jaisy Sep 02 '18 at 23:57
  • this msdn blog was my reference https://blogs.msdn.microsoft.com/devops/2013/10/16/switching-to-managed-compatibility-mode-in-visual-studio-2013/ , its for vs2013 and works also for VS2015 , go through it maybe you missed a step – Wesam Sep 03 '18 at 07:19
  • there is another way actually ,right click and select Properties of your project , go to "Debug" then select the check box "Enable native code debugging" i think this is available in vs for mac – Wesam Sep 03 '18 at 09:35
  • @ZulqarnainJalil , are you still getting the same exception or did it change ? after you did the above – Wesam Sep 15 '19 at 09:57
  • 2
    Use Manager Compatibility Mode resolved this issue for me on VS2019/Win 10. – Kolichikov Jan 30 '20 at 21:03
0

Don't rely on Find since that will go to the cache before DB, especially where you want to retrieve related entities. Also, I believe your treatment of the password is backwards and would not make it through to EF/SQL due to the function to decrypt. So encrypt/hash the provided password from the user and compare that against the already encrypted/hashed data in the database.

string encryptedPassword = AesEncryptAndDecrypt.EncryptString(userView.Password, crytograpyKey, crytograpyIV);
var userData = await _adminGenericRepository.FindBy(x => x.IsActive && x.UserName == userView.UserName && x.Password == encryptedPassword)
    .Select( new     
    {
        UserId = user.UserId,
        IsActive = user.IsActive,
        UserName = user.UserName,
        LastName = user.LastName,
        FirstName = user.FirstName,
        // When using FirstOrDefault, you should have an OrderBy to ensure the selection is predictable.
        SelectedRole = user.RoleAssign.OrderByDescending(x => x.Date).FirstOrDefault()?.Role 
        // Cannot call C# methods here since this will go to SQL.. 
        // If you can populate a UserRoleViewModel in-line, then that can be put here to skip the extra mapping below.
    }).SingleOrDefaultAsync();

// At this point we will have the user details and it's selected Role ready for mapping. 
//This assumes that the mapping of the Role does not rely on any child relationships under the Role.
if (userData != null)
    return new UserViewModel
    {
        UserId = userData.UserId,
        IsActive = userData.IsActive,
        UserName = userData.UserName,
        LastName = userData.LastName,
        FirstName = userData.FirstName,
        SelectedRole = mapRoleDbDataToViewModel(userData.SelectedRole)
    };
else
    return null;
Steve Py
  • 15,253
  • 1
  • 18
  • 29
  • How do you mean the "right way"? About the treatment of the password or populating the view model? Does it not work? – Steve Py Aug 29 '18 at 22:53
  • populating the view model. I haven't tried ... Since lots of code with this approach – San Jaisy Aug 29 '18 at 23:52
  • The extra step to populate a view model (vs. doing it in the EF `.Select()` expression is only if you need to call a C# function (`mapRoleDbDataToViewModel`). EF would attempt to pass that function to SQL Server which will have no knowledge of that function. Instead, if you can create the view model from the related data (`user.RoleAssign.Role`) then you can populate the complete view model structure in one expression. Try it first, figure out how to make it work, then optimize it from there. – Steve Py Aug 30 '18 at 01:01