c# - MVC EF - System.Data.Entity.Infrastruct.DbUpdateException

标签 c# mysql sql-server asp.net-mvc entity-framework

我有两个型号: 用户资料

public class UserProfile
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ApplicationUser ApplicationUser { get; set; }
    public virtual ICollection<UserPost> UserPost { get; set; }
}

用户帖子:

public class UserPost
{  
   [Key]
   [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
   public string Id { get; set; }
   public string PostTitle { get; set; }
   public virtual UserProfile UserProfile { get; set; }
   public string Contents { get; set; }
}

UserProfile 与 AspNetUser 具有一对一的关系。

UserProfile 与 UserPost 具有一对多关系。

当我在 Controller 的 Create 方法中将 UserPost 添加到数据库时,我收到 System.Data.Entity.Infrastruct.DbUpdateException

    [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize]
    public ActionResult Create([Bind(Include = "PostTitle, Content")] UserPost post)
    {
        if (ModelState.IsValid)
        {

            UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db));
            var user = UserManager.FindById(User.Identity.GetUserId());
            post.UserProfile = user.UserProfile;
            db.UserPosts.Add(post);
            db.SaveChanges();//error here
            return RedirectToAction("Index");
        }

        return View(post);
    }

System.Data.Entity.Infrastructure.DbUpdateException occurred HResult=0x80131501 Message=An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.

Inner Exception 1: UpdateException: An error occurred while updating the entries. See the inner exception for details.

Inner Exception 2: SqlException: Cannot insert the value NULL into column 'Id', table 'aspnet-project12017.dbo.UserPosts'; column does not allow nulls. INSERT fails. The statement has been terminated.

最佳答案

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]意味着标有此类属性的列预期具有从 DBMS 自动生成的值,并且作为一般约定,EF 将 stringuniqueidentifier (GUID) 列视为非自动生成的列递增,因此这些列值必须以另一种方式分配(即通过构造函数分配)。

解决主键自增标识列为空问题的常用方法是将其设置为数字数据类型(例如int):

public class UserPost
{  
   [Key]
   [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
   public int Id { get; set; } // change to numeric data type
   public string PostTitle { get; set; }
   public virtual UserProfile UserProfile { get; set; }
   public string Contents { get; set; }
}

然后,在执行迁移时,执行以下步骤:

  1. 有时 EF 默认情况下期望您尝试插入到标识列中。如果发生这种情况,请暂时将 StoreGeneratePattern.NoneDatabaseGenerationOption.None 设置为 UserPost.Id:

    protected void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // other entities
    
        modelBuilder.Entity<UserPost>()
           .HasKey(p => p.Id)
           .Property(p => p.Id)
           .StoreGeneratedPattern = StoreGeneratedPattern.None;
    
       // other entities
    }
    
  2. 确保模型已修改为包含实际的 Id 属性(需要时尝试删除数据库中的 UserPost 表)。

    <
  3. 通过程序包管理器控制台运行迁移,如下所示:

    Add-Migration "Set Id as Identity Specification"
    
  4. DbMigration 生成的类中,您将看到两个方法:Up()Down()。修改 Up() 部分以设置 int 数据类型(并在需要时重新运行迁移过程):

    public override void Up()
    {
        CreateTable(
              "dbo.UserPost",
              c => new
              {
                  Id = c.Int(nullable: false, identity: true),
                  PostTitle = c.String(),
                  Contents = c.String(),
              })
              .PrimaryKey(t => t.Id);                
    }
    

如果您仍希望字符串 Id 列作为 UserPost 的主键,则需要将其设置为 [DatabaseGenerate(DatabaseGenerateOption.None)] 并从类构造函数手动分配值(请注意,生成的值必须是唯一的,否则 EF 会告诉您“无法在对象中插入重复的键”):

public class UserPost
{
    public UserPost()
    {
        Id = [[autogenerated value here]];
    }

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

    // other properties
}

相关问题:

MVC5 EF6 Seed Method: Cannot insert NULL into column 'Id' table AspNetUsers

Cannot insert the value NULL into column 'Id' (Database first)

Code first - Cannot insert the value NULL into column 'Id'

Entity Framework Cannot insert the value NULL into column Identity Specification set to No

关于c# - MVC EF - System.Data.Entity.Infrastruct.DbUpdateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44942632/

相关文章:

c# - 从字节数组创建位图

C# OleDBCommand SQL 语法错误

SQL Server : how to get a database name as a parameter in a stored procedure

php - 使用 Codeigniter 连接到 (Linux)Centos 上的 MS SQL

mySQL REGEXP to SELECT information_schema.COLUMNS 在 COLUMN_NAME 中使用大写字母

c# - Entity Framework v1 - 高流量网站高峰时段出现 "Timeout expired"异常

c# - CaSTLe Windsor - 我是否必须释放单例或非一次性 transient 对象?

c# - 比较 DateTime 值是否为 "between"特定时间

php - 根据列名将查询拆分为多个数组

mysql - SQL 排除匹配所有多个条件的行