【问题标题】:How to retain image data of type varbinary at edit?如何在编辑时保留 varbinary 类型的图像数据?
【发布时间】:2012-11-03 19:55:44
【问题描述】:

我有一个小型演示应用程序来处理存储在数据库中的二进制数据。相关代码见下:

实体类:

    [HiddenInput(DisplayValue = false)]
    public int Id { get; set; }

    [Display(Name = "Full Name:")]
    public string Name { get; set; } 

    [DataType(DataType.Upload)]
    [Display(Name = "Photo:")]
    public byte[] ImageData { get; set; }

    [HiddenInput(DisplayValue = false)]
    public string ImageMimeType { get; set; }

编辑操作:

   [HttpGet]
   public ActionResult Edit(int id)
    {
         var mensPlayer = _dataSource.MensPlayers.FirstOrDefault(p => p.Id == id);

        return View(mensPlayer);
    }

    [HttpPost]
    public ActionResult Edit(MensPlayer mensPlayer, HttpPostedFileBase image)
    {
        if (ModelState.IsValid)
        {
           //Added line below
            _dataSource.ImageTemp(mensPlayerInDb, mensPlayer);
            if (image != null)
            {
                mensPlayer.ImageMimeType = image.ContentType;
                mensPlayer.ImageData = new byte[image.ContentLength];
                image.InputStream.Read(mensPlayer.ImageData, 0, image.ContentLength);
            }
              //Added line below
             mensPlayer.ImageData = mensPlayerInDb.ImageData;

            //Save Player
            _dataSource.Update(mensPlayer);
           _dataSource.Save();
          TempData["message"] = string.Format("{0} has been saved", mensPlayer.Name);
            return RedirectToAction("Detail", "MensPlayer", new {id = mensPlayer.Id});
        }
        return View(mensPlayer);
    }

GetImage 方法:

public FileContentResult GetImage(int id)
    {
        var image = _dataSource.MensPlayers.FirstOrDefault(p => p.Id == id);
        if (image != null)
        {
            return File(image.ImageData, image.ImageMimeType);
        }
        return null;
    }

显示图像:

@if (Model.ImageData != null) {
    <div >
         <img width="300" height="400" src="@Url.Action("GetImage", "MensPlayer",
                                        new { Model.Id })" alt="Player Image"/>
     </div>
 }

数据源类

public interface IDataSource
{
    IQueryable<MensTeam> MensTeams { get; }
    IQueryable<MensPlayer> MensPlayers { get; }
    IQueryable<MensHome> MensHomes { get; }
    void Save();
    void Update(MensPlayer mensPlayer);
    void Delete();
    void ImageTemp(MensPlayer mensPlayerInDb, MensPlayer mensPlayer);//I added this
}

在 Db 类中

void IDataSource.Save()
    {
        SaveChanges();
    }

    void IDataSource.Update(MensPlayer mensPlayer)
    {
        Entry(mensPlayer).State = EntityState.Modified;
    }
     //Added code below
    void IDataSource.ImageTemp(MensPlayer mensPlayerInDb, MensPlayer mensPlayer)
    {
        Entry(mensPlayerInDb).CurrentValues.SetValues(mensPlayer);
    }

我的问题是,每次我尝试编辑播放器时,都会从数据库中很好地检索每个数据,但是当我在编辑后点击保存时,ImageData 会丢失,更像是用空值替换原始数据。就像,应用程序希望我在每次尝试编辑时重新上传图像。

我可以做些什么来清理它?

【问题讨论】:

    标签: asp.net-mvc-4 visual-studio-2012 binary-data entity-framework-5 razor-2


    【解决方案1】:

    好吧,如果imagenull,那么在你的实体中mensPlayer.ImageDatanull。稍后当您调用_dataSource.Update(mensPlayer) 时,您将实体的状态设置为Modified(至少我猜Update 只是将状态设置为Modified),所以您告诉EF 您也修改了图像(即设置为null),EF 将保存该更改。

    为了解决问题,您可以先从数据库中加载包含图像的实体...

    var mensPlayerInDb = context.MensPlayers.Find(mensPlayer.Id);
    mensPlayer.ImageData = mensPlayerInDb.ImageData; // save the ImageData
    // copy changed values to loaded entity and save it, ImageData is unchanged
    context.Entry(mensPlayerInDb).CurrentValues.SetValues(mensPlayer);
    context.SaveChanges();
    

    ...或者你可以试试:

    context.Entry(mensPlayer).State = EntityState.Modified;
    context.Entry(mensPlayer).Property(m => m.ImageData).IsModified = false;
    

    后一种方法不适用于 EF Modified,就禁止将属性的 Modified 状态设置为 false),但它应该适用于 EF 5 .

    您需要将其中一种解决方案集成到您的 _dataSource 服务类中,可能通过引入新方法,因为它不适用于您的一般 Update 方法。

    【讨论】:

    • 对不起,我在生活中遇到了一些事情,但我又回来了。第二个选项看起来很容易实现,但由于第一行将所有内容都设置为修改,所以会吐出一个错误。在第一个选项中,我了解代码归档的内容,但我在实施解决方案时遇到了麻烦。了解并建议我是否走在正确的轨道上。
    • @KomengeMwandila:但是您不会在任何地方使用ImageTemp,也不会从数据库中加载原始图像,对吗?
    • 我已更新编辑操作。但是有一个问题。当我在我的HttpGet中有这条线时,这条线是否需要:var mensPlayerInDb = context.MensPlayers.Find(mensPlayer.Id);var model = _dataSource.MensPlayers.Single(p =&gt; p.Id == id);?我无法理解该行代码中使用的 Find 属性?构建时在我的源代码中显示为红色
    • @KomengeMwandila:你也可以使用Single。您没有Find,因为在您的_dataSource MensPlayer 中是IQueryabl&lt;T&gt; 而不是DbSet&lt;T&gt;
    猜你喜欢
    • 2021-11-15
    • 2018-10-20
    • 1970-01-01
    • 2018-01-10
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 2018-07-21
    相关资源
    最近更新 更多