Невозможно вставить значение NULL в столбец 'RoleId' (простое членство mvc4)

Я заметил, что кто-то другой столкнулся с той же проблемой, например, Невозможно вставить значение NULL в столбец "UserId", но это должно быть вызвано разными причинами.

Проблема может быть упрощена следующим образом:

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

Последняя строка кода вызвала исключение

"Произошла ошибка при обновлении записей. Подробности см. Во внутреннем исключении".

и 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; }
}

и сценарии создания таблицы:

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])
);

Интересно еще и то, что я могу удалить usersInRole из контекста, а именно следующий код в порядке (если я добавил запись вручную):

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

Кажется, мало кто использует и говорит о простом членстве, поэтому я не нашел много полезных ресурсов от Google. Так что любая помощь будет оценена. Благодарю.

Вот решение:

Как сказал Томми, эта проблема вызвана атрибутами [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!
                    }
                }
            }

Кажется, что Roles.AddUserToRole и Roles.RemoveUserFromRole могут сделать это правильно. Но это еще не закончено..... Странно, _userContext.UsersInRoles не может вернуть правильные результаты. Например, если данные в таблице:

RoleId UserId
5      1
5      2
5      3

он возвращает 3 записи (5,1)(5,1)(5,1) вместо (5, 1)(5, 2)(5, 3). Это то, что Томми упомянул в своем ответе, но обошел стороной 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])
    );

2. Добавьте новый столбец к объекту ПРАВО ПОД [КЛЮЧ]:

[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; }
}

Теперь я получаю (5, 1)(5, 2)(5, 3)!

Я мало знаю о базе данных, но, как упоминал Томми, это должно быть вызвано объявлением RoleId в [Key][Database....] с PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC) в сценариях вместе.

2 ответа

Решение

Я думаю, что ваша проблема со следующим разделом

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

Имея Key а также DatabaseGeneratedAttribute говорит EF, что базе данных будет присвоено значение (столбец IDENTITY). Однако ваша база данных не присваивает это значение автоматически. Таким образом, когда EF пытается выполнить вставку, он игнорирует назначенный вами RoleId, потому что считает, что база данных автоматически его назначит. Удалите эти два атрибута в свойстве RoleId и посмотрите, не возникают ли у вас те же проблемы.

1) Почему вы используете DbContext добавить Roles в user? Есть некоторые родные Membership способы сделать это:

Roles.AddUsersToRole(string[] usernames, string rolename)
Roles.AddUserToRole(string username, string rolename) //**This one fits your purpose
Roles.AddUserToRoles(string username, string[] rolenames)
...

2) Значение в ключевом столбце не может быть null

3) Int не может быть null в C#. Если вы хотите установить null значение для int, вы должны определить это как обнуляемый: int?

Другие вопросы по тегам