簡體   English   中英

如何部分更新數據庫記錄?

[英]How to partly update a database record?

我正在努力實現一個簡單的“更新配置文件”功能(學習目的)。 我只是希望每次更新捐贈個人資料時都不能更新個人資料圖片。 當圖片在那里並且配置文件的其他部分已更新時,我希望圖片保持不變。

我想出了以下代碼:

控制器:

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind(Include = "UserDetailsId,ImageData,FirstName,LastName,UserAddress,UserCountry,UserPostalCode,UserPhoneNumber,CompanyId,identtyUserId")] UserDetails userDetails, HttpPostedFileBase UploadImage)
    {
        if (ModelState.IsValid)
        {
            if (UploadImage!=null) {
                byte[] buf = new byte[UploadImage.ContentLength];
                UploadImage.InputStream.Read(buf, 0, buf.Length);
                userDetails.ImageData = buf;
            }
            else {
                var userFromDb = db.UsersDetails.Where(u => u.identtyUserId == userDetails.identtyUserId).First();//i am getting the old user data
                userDetails.ImageData = userFromDb.ImageData; //saving the image to the modified state
            }
            db.Entry(userDetails).State = EntityState.Modified;//error here
            db.SaveChanges();
            return RedirectToAction("Index");

        }
        //ViewBag.CompanyId = new SelectList(db.Companies, "CompanyId", "CompanyName", userDetails.CompanyId);
        return View(userDetails);

我在此行上db.Entry(userDetails).State = EntityState.Modified;的錯誤db.Entry(userDetails).State = EntityState.Modified; 是以下內容:

附加類型為“ eksp.Models.UserDetails”的實體失敗,因為相同類型的另一個實體已經具有相同的主鍵值。 如果圖形中的任何實體具有相互沖突的鍵值,則使用“附加”方法或將實體的狀態設置為“不變”或“修改”時,可能會發生這種情況。 這可能是因為某些實體是新實體,尚未收到數據庫生成的鍵值。 在這種情況下,請使用“添加”方法或“已添加”實體狀態來跟蹤圖形,然后根據需要將非新實體的狀態設置為“未更改”或“已修改”。

該模型 :

public class UserDetails
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int UserDetailsId { get; set; }
    public byte[] ImageData { get; set; }
    [NotMapped]
    public HttpPostedFileBase UploadImage { get; set; }
    [NotMapped]
    public string ImageBase64 => System.Convert.ToBase64String(ImageData);
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string UserPhoneNumber { get; set; }
    public int CompanyId { get; set; }
    public virtual Company Company { get; set; }
    public string identtyUserId { get; set; }
    public virtual ICollection<WorkRolesUsersDetails> WorkRolesUsersDetails { get; set; }

盡管對我來說看起來很自我解釋,但不清楚發生了什么?

有人可以指導我如何實現我想要實現的目標嗎?

謝謝!

更新實體時,應該將發布的值映射到從數據庫拉出的實例上,而不是嘗試直接保存從發布數據創建的實例。 這是避免使用Bind另一個原因,因為它使問題感到困惑,並使更不了解的開發人員認為直接保存從發布數據創建的實體是可以的。 不是,永遠不會。

相反,請使用類似UserDetailsId來查找實體:

var userDetails = db.UserDetails.Find(model.UserDetailsId);

model是您的操作的參數。 然后,您可以將過帳的值映射到您的實體上:

userDetails.FirstName = model.FirstName;
// etc.

最后,保存usersDetails (現在是數據庫的版本),並在適當時將實體上的所有原始數據修改為已發布的數據。

現在,因為你需要在發布的數據要做到這一點映射反正 ,再前進一步可以創建只需要允許用戶修改屬性視圖模型。 然后,您可以發布到該文章 ,而不是使用Bind 真的, Bind很糟糕。 這是Microsoft匆忙添加的內容之一,因為他們認為它解決了一個問題,實際上最終導致了其他十個問題。

無論如何,您都可以從數據庫中檢索數據實體,並使用發布模型中包含的詳細信息對其進行更新,然后將該數據實體保存回數據庫中。

var userFromDb = db.UsersDetails.Where(u => u.identtyUserId == userDetails.identtyUserId).First();
if (UploadImage!=null) 
{
    byte[] buf = new byte[UploadImage.ContentLength];
    UploadImage.InputStream.Read(buf, 0, buf.Length);
    userFromDb.ImageData = buf;
}
userFromDb.FirstName = userDetails.FirstName;
userFromDb.LastName = userDetails.LastName;
userFromDb.UserAddress = userDetails.UserAddress;
userFromDb.UserCountry = userDetails.UserCountry;
userFromDb.UserPostalCode = userDetails.UserPostalCode;
userFromDb.UserPhoneNumber = userDetails.PhoneNumber;
userFromDb.CompanyId = userDetails.CompanyId;
db.SaveChanges();

這應該可以幫助您實現所需的功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM