C# MVC EF-System.Data.Entity.Infrastructure.DbUpdateException
我有两种型号: 用户配置文件C# MVC EF-System.Data.Entity.Infrastructure.DbUpdateException,c#,mysql,sql-server,asp.net-mvc,entity-framework,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; } } U
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; }
}
UserProfile与AspNetUser具有一对一的关系
UserProfile与UserPost具有一对多关系
当我在控制器的Create方法中将UserPost添加到数据库时,我得到一个System.Data.Entity.Infrastructure.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);
}
[HttpPost]
[ValidateAntiForgeryToken]
[授权]
公共操作结果创建([Bind(Include=“postitle,Content”)]UserPost-post)
{
if(ModelState.IsValid)
{
UserManager=newusermanager(newuserstore(db));
var user=UserManager.FindById(user.Identity.GetUserId());
post.UserProfile=user.UserProfile;
db.UserPosts.Add(post);
db.SaveChanges();//此处出错
返回操作(“索引”);
}
返回视图(post);
}
发生System.Data.Entity.Infrastructure.DbUpdateException
HResult=0x8013151
Message=保存未公开其关系的外键属性的实体时出错。EntityEntries属性将返回null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常。有关详细信息,请参见InnerException
内部异常1:UpdateException:更新时出错
条目。有关详细信息,请参见内部异常
内部异常2:SqlException:无法将值NULL插入到
列“Id”,表“aspnet-project12017.dbo.UserPosts”;专栏是这样的
不允许空值。插入失败。声明已终止
表示用该属性标记的列预期具有来自DBMS的自动生成值,并且作为一般约定,EF将string
&uniqueidentifier
(GUID)列视为非自动递增列,因此必须以另一种方式(即通过构造函数赋值)赋值这些列
解决主键自动递增标识列空值问题的常用方法是将其设置为数字数据类型(例如,int
):
然后,在执行迁移时,请执行以下步骤:
StoreGeneratedPattern.None
和DatabaseGenerationOption.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
}
DbMigration
生成的类中,您将看到两种方法:Up()
和Down()
。修改Up()
Id
列作为UserPost
的主键,则需要将其设置为[DatabaseGenerated(DatabaseGeneratedOption.None)]
,并从类构造函数手动分配值(请注意,生成的值必须是唯一的,否则EF将告诉您“无法在对象中插入重复的键”):
相关问题:
将UserPost
Id
列更改为int
:公共int-Id{get;set;}
或将其设置为[数据库生成(数据库生成选项.None)]
。如果您不能将字符串/GUID列设置为自动生成的值列,它只适用于int
、long
或其他数字数据类型(请参见)。@TetsuyaYamamoto因此,如果我想将我的ID保持为字符串,在创建新帖子时如何生成它,因为它不是自动生成的?您可以从类构造函数手动生成它,类似于public UserPost(){Id=Guid.NewGuid().ToString();}
。当然,您可以在那里设置另一个值而不是GUID。我尝试将Id更改为int,但仍然出现相同的错误@Tetsuyayamamoto这是代码优先,对吗?如果您已经在使用数据创建数据库&仍然遇到相同的错误,请使用EF Code First迁移来更改标识列数据类型。只要目标表中Id
的数据类型不变,EF仍然将该列视为string
,而不是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; }
}
protected void OnModelCreating(DbModelBuilder modelBuilder)
{
// other entities
modelBuilder.Entity<UserPost>()
.HasKey(p => p.Id)
.Property(p => p.Id)
.StoreGeneratedPattern = StoreGeneratedPattern.None;
// other entities
}
Add-Migration "Set Id as Identity Specification"
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);
}
public class UserPost
{
public UserPost()
{
Id = [[autogenerated value here]];
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string Id { get; set; }
// other properties
}