Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何部分更新数据库记录?_C#_Asp.net Mvc_Entity Framework_Linq - Fatal编程技术网

C# 如何部分更新数据库记录?

C# 如何部分更新数据库记录?,c#,asp.net-mvc,entity-framework,linq,C#,Asp.net Mvc,Entity Framework,Linq,我正在努力实现一个简单的“更新配置文件”功能(学习目的)。我只是不想每次更新给定的配置文件时都更新配置文件映像。当图片在那里,并且个人资料的其他部分被更新时,我希望图片保持不变 我为此想出了以下代码: 控制器: [HttpPost] [ValidateAntiForgeryToken] public ActionResult Edit([Bind(Include = "UserDetailsId,ImageData,FirstName,LastName,UserAddress,U

我正在努力实现一个简单的“更新配置文件”功能(学习目的)。我只是不想每次更新给定的配置文件时都更新配置文件映像。当图片在那里,并且个人资料的其他部分被更新时,我希望图片保持不变

我为此想出了以下代码:

控制器:

[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如下所示:

附加“eksp.Models.UserDetails”类型的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”

模型:

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; }
公共类用户详细信息
{
[关键]
[数据库生成(DatabaseGeneratedOption.Identity)]
public int UserDetailsId{get;set;}
公共字节[]图像数据{get;set;}
[未映射]
公共HttpPostedFileBase上载映像{get;set;}
[未映射]
公共字符串ImageBase64=>System.Convert.ToBase64String(ImageData);
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串UserPhoneNumber{get;set;}
public int CompanyId{get;set;}
公共虚拟公司公司{get;set;}
公共字符串identityuserid{get;set;}
公共虚拟ICollection工作角色用户详细信息{get;set;}
虽然对我来说这看起来很自我解释,但不清楚这是怎么回事

有人能指导我如何实现我想实现的目标吗


谢谢!

您可以在任何情况下从数据库中检索数据实体,并使用作为Post模型一部分的详细信息对其进行更新,然后将该数据实体保存回数据库

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();

这将帮助您实现所需的功能。

您可以在任何情况下从数据库中检索数据实体,并使用作为Post模型一部分的详细信息对其进行更新,然后将该数据实体保存回数据库

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();

这将帮助您实现所需的功能。

当您更新实体时,您应该将发布的值映射到从数据库中提取的实例上,而不是试图直接保存从发布数据创建的实例。这是避免使用
绑定的另一个原因,因为它会混淆问题并使开发人员感到困惑不知道的人认为直接保存从post数据创建的实体是可以的。事实并非如此,而且永远不会

相反,使用类似于
UserDetailsId
的方法来查找实体:

var userDetails = db.UserDetails.Find(model.UserDetailsId);
其中,
model
是您操作中的参数。然后,您可以将发布的值映射到实体上:

userDetails.FirstName = model.FirstName;
// etc.
最后,保存
usersDetails
,它现在是数据库中的版本,包含实体上的所有原始数据,并在适当的情况下修改为发布的数据


现在,考虑到您无论如何都需要对发布的数据进行映射,再进一步,您可以创建一个视图模型,其中只包含您需要允许用户修改的属性。然后您可以发布到该视图模型,而不是使用
Bind
。实际上,
Bind
非常糟糕。这是Microsoft匆忙添加的内容之一,因为当你更新一个实体时,你应该将发布的值映射到从数据库中提取的实例上,而不是试图直接保存从post数据创建的实例。这是避免使用
Bind
的另一个原因,因为它混淆了issue和make让不太了解的开发人员认为直接保存post数据创建的实体是可以的。事实并非如此,也永远不会如此

相反,使用类似于
UserDetailsId
的方法来查找实体:

var userDetails = db.UserDetails.Find(model.UserDetailsId);
其中,
model
是您操作中的参数。然后,您可以将发布的值映射到实体上:

userDetails.FirstName = model.FirstName;
// etc.
最后,保存
usersDetails
,它现在是数据库中的版本,包含实体上的所有原始数据,并在适当的情况下修改为发布的数据


现在,考虑到您无论如何都需要对发布的数据进行映射,再进一步,您可以创建一个视图模型,其中只包含您需要允许用户修改的属性。然后您可以发布到该视图模型,而不是使用
Bind
。实际上,
Bind
非常糟糕。这是Microsoft匆忙添加的内容之一,因为认为它解决了一个问题,但实际上却导致了十个其他问题。

可能的重复我不确定这是否是一个理想的解决方案,但您是否考虑过先获取记录,修改它,然后将其发送回?服务器可能足够聪明,不会修改未更改的字段。@JamesHughes有可能吗要演示这个吗?@RobertRoss,恐怕现在还没有,如果你还没有得到公认的答案,我会为你拿出一些演示代码tonight@JamesHughes好的,谢谢!可能是重复的我不确定这是否是一个理想的解决方案,但您是否考虑过先获取记录,修改它,然后将其发送回?服务器可能是智能的不能修改未更改的字段。@JamesHughes可以演示吗?@RobertRoss,现在恐怕不行,如果你还没有得到公认的答案,我会为你提供一些演示代码tonight@JamesHughes好的,谢谢!在这种情况下,只有修改图像本身,我才能修改记录,这不是我想要的:(根据您发布的代码,仅更改对象的图像属性?是否还有其他内容?)