db.SaveChanges()上的异常。我是否正确?提供具有正确代码的解决方案

时间:2014-07-19 21:49:26

标签: entity-framework

我已将主键(Userid)作为“Book”表中的外键。它是一对多关系,即单个用户可以上传多本书。 BookID自动递增。当用户点击“上传图书”按钮时,我需要将图书的名称及其路径存储在数据库中,其中userid作为外键来自User表和BookID以自动增加

我在db.SaveChanges()处遇到以下异常:

  

EntityFramework.dll中发生了'System.Data.Entity.Infrastructure.DbUpdateException'类型的异常但未在用户代码中处理附加信息:更新条目时发生错误。有关详细信息,请参阅内部异常。

内部例外是:

  

无法将值NULL插入列'Id',表'BooksModule.dbo.Book';列不允许空值。 INSERT失败。\ r \ n语句已终止。

以下是我的代码:

这是我的模型类:Book.cs

public partial class Book
{
    public string Id { get; set; }
    public int BookID { get; set; }
    public string BookName { get; set; }
    public string BookPath { get; set; }

    public virtual User User { get; set; }
}

这是我的用户模型类:User.cs

public partial class User
{
    public User()
    {
        this.Books = new HashSet<Book>();
    }

    public string Id { get; set; }
    public string UserName { get; set; }

    public virtual ICollection<Book> Books { get; set; }
}

这是一个方法:

[HttpGet]
public ActionResult FileUpload(string id)
{
    return View();
}

[HttpPost]
public ActionResult FileUpload(HttpPostedFileBase file,Book bk)
{
        var filepath = "";
        var fname = "";
        if (ModelState.IsValid)
        {
            if (file.ContentLength > 0)
            {
                var fileName = Path.GetFileName(file.FileName);
                var path = Path.Combine(Server.MapPath("~/App_Data/Uploads"), fileName);
                filepath = path;
                fname = fileName;
                file.SaveAs(path);
            }
            bk.BookName = fname;
            bk.BookPath = filepath;
            db.Books.Add(bk);
            db.SaveChanges();
            return RedirectToAction("Index", "Home");
        }
        else
        {
            return View();
        }      
    }

以下是一个观点:

<div class="sidebar">
    @using (Html.BeginForm("FileUpload", "UploadBooks", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        @Html.ValidationSummary();
        <fieldset>
            <legend>Upload a file</legend>
            <div class="editor-field">
            @Html.TextBox("file", "", new { type = "file" })
            </div>

            <input type="submit" id="btnSubmit" class="btn btn-default2" value="Upload" />

        </fieldset>
    }

</div>

1 个答案:

答案 0 :(得分:1)

实体框架将选择Id作为主键,而您自己需要string来提供它(您不会这样做。)

最好使用int作为主键,以便EF可以使其成为数据库中的identity列。

其他一些观察结果:

  1. FileUpload帖子操作正在使用一个Book对象,该对象除了作为操作中的变量之外没有被使用,而只是在方法中声明一个新的Book对象。 / LI>
  2. 不需要fileNamepath个变量。
  3. 您是否同时需要IdBookId?我会删除BookId
  4. 我建议您Book.cs看起来像这样:

    public partial class Book
    {
        public int Id { get; set; }
    
        public string BookName { get; set; }
        public string BookPath { get; set; }
    
        public virtual User User { get; set; }
    }
    

    你的帖子:

    [HttpPost]
    public ActionResult FileUpload(HttpPostedFileBase file)
    {
        if (ModelState.IsValid)
        {
            if (file.ContentLength > 0)
            {
                fname = Path.GetFileName(file.FileName);
                filepath = Path.Combine(Server.MapPath("~/App_Data/Uploads"), fileName);
                file.SaveAs(fname);
    
                Book bk = new Book
                {
                    BookName = fname,
                    BookPath = filepath
                };
    
                db.Books.Add(bk);
                db.SaveChanges();
    
            }
    
            return RedirectToAction("Index", "Home");
        }
        else
        {
            return View();
        }      
    }
    

    <强>更新

    根据您上面的评论,您需要对Book课程进行其他更改。首先,如果密钥使用Id属性,您需要告诉实体框架您的[Key]属性。其次,对于Id列,您应该执行以下操作之一:

    1. 删除Id(因为实体框架会为您创建一个)
    2. Id重命名为UserId,以允许Entity Framework自动将其链接到User属性。
    3. User属性添加属性,告诉它要使用的列的名称,例如[ForeignKey("Id")]
    4. 我建议使用1或2,这样在查看数据库时列更明显:

      public partial class Book
      {
          [Key]
          public int BookId { get; set; }
      
          public string BookName { get; set; }
          public string BookPath { get; set; }
      
          public string UserId { get; set; }
          public virtual User User { get; set; }
      }