【问题标题】:Edit entity in database and reuse stored image编辑数据库中的实体并重用存储的图像
【发布时间】:2015-02-16 17:29:09
【问题描述】:

我在 asp.net MVC 5 (vb.net) 中使用实体框架来存储一些数据,包括图像 (png)。图像可以作为 Byte() 保存到数据库中,但是一旦我编辑任何现有实体而不上传新图像,存储的图像就会被删除。所以我尝试了this 并在编辑控制器中编写了以下代码:

       If ModelState.IsValid Then
            If Request.Files("Image").ContentLength <> 0 Then
                dbModel.Image = dbModel.ImageToByte(Request.Files("Image")) 'Function to create Byte() --> this works
            Else
                dbModel.Image = db.Content.Find(dbModel.ID).Image 'This line is responsible for the exception
            End If
            db.Entry(dbModel).State = EntityState.Modified  'Here the exception occours!
            db.SaveChanges()
            Return RedirectToAction("Index")
        End If

在 EntityState 设置为 Modified 的行中,发生了异常:

EntityFramework.dll 中出现“System.InvalidOperationException”类型的异常,但未在用户代码中处理

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

我猜,从数据库中加载现有图像的那一行是导致异常的原因,但我真的不知道该怎么办。

【问题讨论】:

  • 您可能可以删除整行db.Entry(dbModel).State = EntityState.Modified,因为我假设dbModel 已被跟踪,因此EF 将在您修改它时存储其更改。但是你有没有考虑过分表?
  • @GertArnold:感谢您对拆分表的提示。我试图删除这一行,但现在数据库没有更新。

标签: asp.net-mvc vb.net entity-framework


【解决方案1】:

使用视图模型。您遇到的问题是因为 Image 字段被回发为 null,因为没有设置新图像,所以当您更新实体时,它会将 Image 设置为该 null 值。实际上,通过不发布 Image 的值,您实际上是在告诉 Entity Framework 您想将该值设为空。

通过使用视图模型,您可以只处理视图中需要的字段,然后将发布的值映射回您的实体。这意味着像Image 这样的属性仍然具有从数据库中检索到的值。例如:

public class FooViewModel
{
    // other properties here

    public HttpPostedFileBase Image { get; set; }
}

那么在你的行动中:

public ActionResult Edit(int id, FooViewModel model)
{
    var foo = db.Foos.Find(id);
    if (foo == null)
    {
        return new HttpNotFoundResult();
    }

    // Map properties over
    // foo.Bar = model.Bar;
    if (model.Image != null && model.Image.ContentLength > 0)
    {
        foo.Image = foo.ImageToByte(model.Image);
    }

    ...
}

【讨论】:

  • 谢谢。我已经尝试过这种方法,因为视图模型似乎是更好的做法than exposing the database model。但最后,当条目更新时,我遇到了同样的异常。
【解决方案2】:

最后我得到了这个解决方案。

Function Edit(<Bind(Include:="ImageFile,Image")> ByVal Model As dbModel, ByVal ImageFile As HTTPPostedFileBase) As ActionResult
    If ModelState.IsValid Then
        Dim Current As dbModel = db.Content.Find(Model.ID)  'Get the original entry.
        If Not ImagFile is Nothing Then
            Model.Image = Model.ImageToByte(ImageFile) 'Function to create Byte()
        Else
            Model.Image = db.Content.Find(Model.ID).Image
        End If
        'db.Entry(dbModel).State = EntityState.Modified  'Here the exception occoured before.
        db.Entry(Current).CurrentValues.SetValues(Model) 'This line is new and solved the problem!
        db.SaveChanges()
        Return RedirectToAction("Index")
    End If
    Return View(Model)
End Function

为了完整起见,这里是将 HTTPPostedFileBase 转换为 Byte() 的代码:

Public Function ImageToByte(ByVal Img As HttpPostedFileBase) As Byte()
    Dim Image As New MemoryStream
    Img.InputStream.CopyTo(Image)
    Return Image.ToArray()
End Function

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-29
    • 2018-08-03
    • 2020-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-07
    相关资源
    最近更新 更多