4

我正在阅读 Apress 的 Pro ASP.NET MVC 3 Framework。我正在遵循上传和显示图像的示例。问题是它在将图像上传到产品时工作正常,但如果我稍后想编辑描述,然后保存产品,图像就会消失。我知道问题是在保存产品时我没有传递图像数据,因为图像上传是空的,并且 context.SaveChanges() 保存了每个数据字段,包括空的图像数据字段。

我被困住了,如果有人可以帮助我,我将不胜感激!

这是编辑页面的一部分:

<label>Image</label> 
if (Model.ImageData == null)
{ 
    @:Null
}
else
{ 
    <img id="imageFile" runat="server" src="@Url.Action("GetImage", "Product", new { Model.Name })" /> 
}
<label>Upload image:</label>
<input type="file" name="Image" runat="server"  />

更新时:

public ActionResult Edit(Product product, HttpPostedFileBase image)
    {
        if (ModelState.IsValid)
        {
            if (image != null && image.ContentLength > 0)
            {
                product.ImageMimeType = image.ContentType;
                product.ImageData = new byte[image.ContentLength];
                image.InputStream.Read(product.ImageData, 0, image.ContentLength);
            }
            repository.SaveProduct(product);
            TempData["message"] =  string.Format("{0} har sparats", product.Name);
            return RedirectToAction("Index");
        }
        else
        {
            return View(product);
        }
    }

保存产品:

public void SaveProduct(Product product)
    {
        if (product.ProductID == 0)
        {
            context.Products.Add(product);
        }
        else
        {
            context.Entry(product).State = EntityState.Modified;
        }
        int result = context.SaveChanges();
    }
4

3 回答 3

4

您对问题的理解是正确的:当您将您的标记ProductEntityState.ModifiedEF 时,它的所有属性都已修改。因此,当您的电流Product来自控制器并且没有图像时,EF 会在调用SaveChanges().
我看到两个选项:

  1. 您加载原始Product文件并仅更新 using 所需的属性EntityState.Modified

    var productInDb = context.Products.Find(product.Id);
    productInDb.Name = product.Name;
    productInDb.Description = product.Description;
    if (product.ImageData !=null )
    {
        productInDb.ImageData = product.ImageData;
        productInDb.ImageMimeType = product.ImageMimeType;
    }
    

    在这种情况下,您必须手动设置Product.

  2. 将您的标记Product为已修改后,您可以从数据库中重新设置图像值:

    context.Entry(product).State = EntityState.Modified;
    if (product.ImageData == null)
    {
        var databaseValues = context.Entry(product).GetDatabaseValues();
        product.ImageData = (byte[])databaseValues["ImageData"];
        product.ImageMimeType = (string)databaseValues["ImageMimeType"];
    }
    

    在这种情况下,您只需要重新设置图像相关属性。

使用这两种实现方式都无法在更新期间删除 ImageData。

于 2011-12-11T11:02:57.213 回答
0

如果您尝试@nemesv 提供的第二个选项,并且您的实体类与您的 DbContext 位于不同的命名空间中,那么您将遇到实体框架引发的异常,如下所述:

entry.GetDatabaseValues() 抛出 EntitySqlException

找不到类型“XXX”。确保加载了所需的模式并且正确导入了命名空间。

http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/fa67aa0e-3bca-44a5-9e00-af6362a539a7

似乎有一种解决方法,但它并不令人愉快。不过,它确实允许图像与产品保持关联。

这是我的做法:

if (product.ImageData == null)
{
    // Get Product Context reference
    var productContext = context.Entry(product);
    productContext.State = EntityState.Modified;

    // Copy client values and reload orignal product values from DB.
    var clientValues = productContext.CurrentValues.Clone().ToObject();
    productContext.Reload();
    productContext.CurrentValues.SetValues(clientValues);

    // Get database values (Original)
    var currentValues = productContext.Entity;
    var databaseValues = (Product)productContext.OriginalValues.ToObject();

    // Change image properties to match original values
    productContext.Entity.ImageData = databaseValues.ImageData;
    productContext.Entity.ImageMimeType = databaseValues.ImageMimeType;
}
于 2012-02-15T00:02:14.927 回答
0

我有一个类似的问题。当我添加@Html.HiddenFor(model => model.Image)到我的编辑视图时,它完美地传递了 imageURL。

于 2015-07-22T18:31:13.403 回答