无法将值NULL插入"RoleId"列(mvc4简单成员资格)

che*_*eny 0 asp.net-mvc-4 simplemembership

我注意到其他人遇到了同样的问题,例如无法将值NULL插入"UserId"列,但这应该是由不同的原因引起的.

这个问题可以像这样简化:

            UsersContext _usersContext = new UsersContext();
            ...
            var usersInRole = new UsersInRole() { RoleId = 3, UserId = 1 };
            _usersContext.UsersInRoles.Add(usersInRole);
            _usersContext.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

最后一行代码引发了异常

"更新条目时发生错误.有关详细信息,请参阅内部异常."

,而且InnerException也说了同样的话

"更新条目时发生错误.有关详细信息,请参阅内部异常."!

幸运的是,InnerException的InnerException说

"无法将值NULL插入列'RoleId',表'MFC.dbo.webpages_UsersInRoles';列不允许空值.INSERT失败.\ r \n语句已终止."

.这意味着"RoleId = 3"被修改或忽略,这怎么可能发生?

下面列出了一些其他可能有用的代码:

[Table("webpages_UsersInRoles")]
public partial class UsersInRole
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int RoleId { get; set; }
    public int UserId { get; set; }
}

public class UsersContext : DbContext
{
    public UsersContext()
        : base("MFCConnectionString")
    {
    }

    public DbSet<UsersInRole> UsersInRoles { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

和表创建脚本:

CREATE TABLE [dbo].[webpages_UsersInRoles] (
    [UserId] INT NOT NULL,
    [RoleId] INT NOT NULL,
    PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
    CONSTRAINT [fk_UsersInRoels_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[webpages_Roles] ([RoleId]),
    CONSTRAINT [fk_UsersInRoles_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[UserProfile] ([UserId])
);
Run Code Online (Sandbox Code Playgroud)

另一件事是我可以从上下文中删除usersInRole,即,以下代码是可以的(如果我手动添加了记录):

            UsersContext _usersContext = new UsersContext();
            ...
            var usersInRole = _usersContext.UsersInRoles.SingleOrDefault(i => i.RoleId == 3 && UserId == 1);
            _usersContext.UsersInRoles.Remove(usersInRole);
            _usersContext.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

似乎很少有人使用和谈论简单的会员资格,因此我从谷歌找不到很多有用的资源.所以任何帮助将不胜感激.谢谢.

这是解决方案:

正如Tommy所说,这个问题是由[Key]属性引起的.而不是删除[Key](这将导致像"实体类型没有定义键"这样的错误),我将代码更改为官方解决方案:

            foreach (var role in roles)
            {
                foreach (var user in UserProfile.GetAllUserProfiles(_usersContext))
                {
                    var usersInRole = _usersContext.UsersInRoles.SingleOrDefault(uio => uio.RoleId == role.RoleId && uio.UserId == user.UserId);
                    var key = user.UserId + "_" + role.RoleId;
                    if (collection.AllKeys.Any(i => i == key) && collection[key].Contains("true") && usersInRole == null)
                    {
                        Roles.AddUserToRole(user.UserName, role.RoleName); //Key codes!
                    }
                    if (collection.AllKeys.Any(i => i == key) && !collection[key].Contains("true") && usersInRole != null)
                    {
                        Roles.RemoveUserFromRole(user.UserName, role.RoleName); //Key codes!
                    }
                }
            }
Run Code Online (Sandbox Code Playgroud)

似乎Roles.AddUserToRole和Roles.RemoveUserFromRole可以正确地完成它.但它尚未完成.....奇怪的是,_userContext.UsersInRoles无法返回正确的结果.例如,如果表中的数据是:

RoleId UserId
5      1
5      2
5      3
Run Code Online (Sandbox Code Playgroud)

它返回3个记录(5,1)(5,1)(5,1)而不是(5,1)(5,2)(5,3).这是Tommy在回复中提到的但被Roles.Add/Remove()绕过的东西.解决方案是:1.向表中添加[ID]列:

    CREATE TABLE [dbo].[webpages_UsersInRoles] (
        [ID] INT NOT NULL IDENTITY, --Key codes!
        [UserId] INT NOT NULL,
        [RoleId] INT NOT NULL,
        PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
        CONSTRAINT [fk_UsersInRoels_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[webpages_Roles] ([RoleId]),
        CONSTRAINT [fk_UsersInRoles_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[UserProfile] ([UserId])
    );
Run Code Online (Sandbox Code Playgroud)

2.将新列添加到[KEY]下的实体RIGHT:

[Table("webpages_UsersInRoles")]
public partial class UsersInRole
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; } //Key codes!
    public int RoleId { get; set; }
    public int UserId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在我得到(5,1)(5,2)(5,3)!

我对数据库知之甚少,但是正如Tommy所提到的,这应该是通过在[Key] [Database ....]下使用PRIMARY KEY CLUSTERED([UserId] ASC,[RoleId] ASC)一起声明RoleId引起的.

Tom*_*mmy 7

我认为您的问题在于以下部分

public partial class UsersInRole
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int RoleId { get; set; }
    public int UserId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

拥有KeyDatabaseGeneratedAttribute告诉EF数据库将分配值(IDENTITY列).但是,您的数据库不会自动分配此值.因此,当EF尝试执行插入时,它忽略了您分配的RoleId,因为它认为数据库将自动分配它.删除RoleId属性上的这两个属性,看看是否仍然存在相同的问题.