2017-01-25 9 views
0

Entity Framework 6, MVC5, ASP Identity 2.0.MVC5 EF6 Метод семян: не может вставить NULL в таблицу «Id» AspNetUsers

Я следовал за это 2 обучающие программы, чтобы создать регистрационную часть веб-приложения: part 1 - part 2

Я создал свой собственный класс AppUser из IdentityUser класса в другом проекте библиотеки. У меня также есть контекст данных от IdentityDbContext

public class DataContext: IdentityDbContext<AppUser> 
    { 
     public DataContext(): base("DefaultConnection") { } 

     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      modelBuilder.Entity<AppUser>().Property(u => u.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity); 
      base.OnModelCreating(modelBuilder); 
     } 
    } 

public class AppUser : IdentityUser 
{ 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    [Key] 
    public override string Id { get; set; } 

    [Required] 
    [Display(Name ="First Name")] 
    [MaxLength(100)] 
    public string FirstName { get; set; } 

    [Required] 
    [Display(Name = "Last Name")] 
    [MaxLength(100)] 
    public string LastName { get; set; } 

    [MaxLength(100)] 
    public string Title { get; set; } 

    [Required(ErrorMessage = "Email is required.")] 
    [Display(Description = "Email")] 
    public override string Email { get; set; } 

    [MaxLength(20)] 
    public string Phone { get; set; } 

    [Range(0,9999)] 
    [Display(Name = "Extension")] 
    public int PhoneExtension { get; set; } 

    [Display(Name = "Active")] 
    [DefaultValue(true)] 
    public bool IsActive { get; set; } 
} 

Когда я запускаю метод семян я получаю следующую ошибку

System.Data.SqlClient.SqlException: Невозможно вставить значение NULL в столбец «Id ', таблица' CRM1.dbo.AspNetUsers '; столбец не допускает нулей. INSERT терпит неудачу. Заявление было прекращено.

Вот метод высева:

protected override void Seed(CRM.DAL.Data.DataContext context) 
    { 
     context.AccessLevels.AddOrUpdate(al => al.Label, 
      new Model.AccessLevel { AccessLevelID = 1, Label = "Admin", Description = "Full access to the CRM data" }, 
      new Model.AccessLevel { AccessLevelID = 2, Label = "Customer Service", Description = "Full access to the CRM data" }, 
      new Model.AccessLevel { AccessLevelID = 3, Label = "Sales", Description = "Full access to the CRM data" } 
      ); 

     if (!(context.Users.Any(u => u.UserName == "[email protected]"))) 
     { 
      var userStore = new UserStore<AppUser>(context); 
      var userManager = new UserManager<AppUser>(userStore); 
      var userToInsert = new AppUser 
      { 
       Id = "1", 
       FirstName = "Admin", 
       LastName = "Admin", 
       Title = "Administrator", 
       Email = "[email protected]", 
       PhoneExtension = 0, 
       IsActive = true, 
       AccessLevelID = 1, 
       EmailConfirmed = true, 
       PhoneNumberConfirmed = true, 
       TwoFactorEnabled = false, 
       LockoutEnabled = false, 
       AccessFailedCount = 0, 
       UserName = "admin" 
      }; 
      userManager.Create(userToInsert, "password"); 
     } 

    } 

Так Id получает значение, но EF говорит он вставляет NULL. Я пытался, не придавая значения Id мышлению, EF будет делать это автоматически, но нет.

Каков подход к посещению AspNetUser с моим контекстом? Я видел разные учебники, но это не относится к моему расширенному классу AppUser и DataContext.

Спасибо

+0

Попробуйте изменить тип Id в целое и посмотреть, что происходит –

+0

Можете ли вы подтвердить, что 'столбец Id' был создан в качестве столбца идентификации? – markpsmith

+0

@kkkkk Изменение идентификатора в int говорит о том, что он не соответствует типу наследуемого идентификатора от IdentityUser – Greg

ответ

1

Удалить эту строку из кода:

modelBuilder.Entity<AppUser>().Property(u => u.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity); 

, а также эта часть из вашего User:

[DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
[Key] 
public override string Id { get; set; } 

Вам не нужно переопределить это свойство, просто используйте свойство parent (структура объекта будет отображать его).

Объяснение: при настройке Id свойства, как ваши, вы рассказываете рамки сущности значения свойства поступает из базы данных, поэтому она полностью игнорирует значение передается это свойство при вставке в базу данных.

С другой стороны, если ваша колонка внутри вашей таблицы базы данных не имеет значения по умолчанию, она будет терпеть неудачу, поскольку структура сущности не предоставляет для нее значение.

Поэтому вам нужно решить: либо ваша таблица должна иметь значение по умолчанию, либо вы должны удалить эту опцию HasDatabaseGeneratedOption для этого поля.

Дело в том, что IdentityUser использует ключ string, который обычно был бы Guid. Поскольку EF не будет генерировать Id для вас автоматически, и столбец будет не так, вы можете создать constructor ваши User сделать так:

public AppUser() 
{ 
    Id = Guid.NewGuid().ToString(); 
} 

При создании нового пользователя, он будет иметь новый Guid как Id ....когда вы читаете существующего пользователя из вашего контекста, хотя ваш конструктор будет генерировать его при создании EF, EF затем загрузит значение Id из вашей таблицы над ним (игнорируя тот, который указан в конструкторе).

Это означает, что автогенерированное Guid внутри вашего конструктора будет использоваться только для новых экземпляров.

+0

Я попытался удалить эту строку, и я получаю такой же результат. Поэтому я также удалил переписывание поля Id в AppUser, потому что я использовал атрибут на нем. Тогда это сработало. В будущем, с передней стороны, EF будет генерировать Id автоматически? – Greg

+0

@Greg Нет, это не так, но я отредактировал свой ответ с возможным решением для вашего дела. – Alisson

+0

По какой-то причине я попытался запустить метод семени, не предоставив идентификатор моему пользователю для вставки, и EF дал мне «3a66c954-393f-42e2-b810-36a044d7a0b2» ..... поэтому я не использовал Id = Guid. NewGuid(). ToString(). Спасибо в любом случае – Greg

1

Со мной произошло следующее. Я выполнил это руководство, чтобы изменить основной ключ для пользователей в ASP.NET Identity от Guid до Int.

https://docs.microsoft.com/en-us/aspnet/identity/overview/extensibility/change-primary-key-for-users-in-aspnet-identity

Я уже сделал несколько миграций так EF пытался изменить Id из NVARCHAR (128) в целое. Это сработало, но Identity Specification никогда не поворачивалось от No to Yes. Решив его, удалив все предыдущие миграции, удалив базу данных, а затем сделайте новую миграцию для всех изменений. Поскольку мы были на ранней стадии разработки, это не проблема.

enter image description here