首页 > 解决方案 > 该属性是键的一部分,因此不能修改或标记为已修改

问题描述

添加加密后,我似乎无法添加用户角色。由于我收到以下错误:

无法跟踪实体类型“UserRole”的实例,因为已经在跟踪具有相同键值 {'Username', 'Rolename'} 的另一个实例。

但是,我不确定我在哪里跟踪记录,因为我现在才创建它。为什么现在我改变了问题出现的价值观?而且我对这些表没有外键约束。反正还没有。

调用代码:

async void AddUser()
{
    var userAdded = await UserService.AddUser(User, Role, Password);
    if (userAdded)
    {
        await UserService.AddUserRole(User, Role);
        UserRoles.Add(new UserRole() { Username = User, Rolename = Role });
    }

    User = string.Empty;
    Password = string.Empty;

    StateHasChanged();
}

添加用户代码:

public async Task<bool> AddUser(string username, string role, string password)
{
    if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(role) || string.IsNullOrEmpty(password))
        return false;

    var usernameEncrypt = MarelEncryption.EncryptString(username); // 4gXmaWCArsBPjeJfIyX5qg==
    var user = await UserRepository.FirstOrDefaultAsync(x => x.Username == usernameEncrypt);

    if (user == null)
    {
        var passwordEncrypt = MarelEncryption.EncryptString(password); // 4gXmaWCArsBPjeJfIyX5qg==
        await UserRepository.CreateAsync(new Users() { Password = passwordEncrypt, Username = usernameEncrypt });
        return true;
    }
    else
    {
        return false;
    }
}

添加用户角色:

public async Task<bool> AddUserRole(string username, string role)
{
    var userrole = await UserRolesrepository.FirstOrDefaultAsync(x => x.Username == username && x.Rolename == role);

    if (userrole == null)
    {
        var userEncrypt = MarelEncryption.EncryptString(username); // 3qsWsTYQYtIDKxk5rLCb5w==
        var roleEncrypt = MarelEncryption.EncryptString(role); // PmWB4sczzBA5jGY2MePNdg==
        await UserRolesrepository.CreateAsync(new UserRole() { Username = userEncrypt, Rolename = roleEncrypt }); // <--- ERROR
    }

    return true;
}

附加信息

下面我有流畅的 API 代码

/* UserRoles */
modelBuilder.Entity<UserRole>(entity =>
{
  entity.HasKey(e => new { e.Username, e.Rolename });
});

标签: c#entity-frameworkasp.net-core

解决方案


我当然无法对此进行测试,但从查看代码来看,这是我最好的猜测。

当您检查现有用户时,您正在使用用户名的加密版本来检查它是否已经存在:

var usernameEncrypt = MarelEncryption.EncryptString(username); // 4gXmaWCArsBPjeJfIyX5qg==
var user = await UserRepository.FirstOrDefaultAsync(x => x.Username == usernameEncrypt);

但是,当您检查用户角色时,您是在检查后进行加密,所以我的猜测是它将始终返回 `null,然后您将保存加密的角色:

var userrole = await UserRolesrepository.FirstOrDefaultAsync(x => x.Username == username && x.Rolename == role);

if (userrole == null) //im guessing this is always true
{
    var userEncrypt = MarelEncryption.EncryptString(username); // 3qsWsTYQYtIDKxk5rLCb5w==
    var roleEncrypt = MarelEncryption.EncryptString(role); // PmWB4sczzBA5jGY2MePNdg==
    await UserRolesrepository.CreateAsync(new UserRole() { Username = userEncrypt, Rolename = roleEncrypt }); // <--- ERROR
}

我会在检查之前移动加密,就像您为用户所做的那样:

var userEncrypt = MarelEncryption.EncryptString(username); // 3qsWsTYQYtIDKxk5rLCb5w==
var roleEncrypt = MarelEncryption.EncryptString(role); // PmWB4sczzBA5jGY2MePNdg==
var userrole = await UserRolesrepository.FirstOrDefaultAsync(x => x.Username == userEncrypt && x.Rolename == roleEncrypt);

if (userrole == null)
{
    await UserRolesrepository.CreateAsync(new UserRole() { Username = userEncrypt, Rolename = roleEncrypt }); // <--- ERROR
}

推荐阅读