1

データベースに保存されているバイナリデータを回避するための小さなデモアプリケーションがあります。関連するコードについては、以下を参照してください。

エンティティクラス:

    [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>
 }

DataSourceクラス

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

私の問題は、プレーヤーを編集しようとするたびに、すべてのデータがデータベースから適切に取得されることですが、編集後に保存を押すと、元のデータをnull値に置き換えるように、ImageDataが失われます。まるで、アプリケーションは、編集を試みるたびに画像を再アップロードすることを期待しています。

これをクリーンアップするにはどうすればよいですか?

4

1 に答える 1

0

もしimagenullあなたのエンティティにあるなら、mensPlayer.ImageDataですnull。後で呼び出すとき_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 < 5.0 では機能しませんでした (エンティティが としてマークされた後にModifiedプロパティの状態をに設定することは禁止されていたため) が、EF 5 では機能するはずです。falseModified

_dataSource一般的なメソッドでは機能しないため、おそらく新しいメソッドを導入して、ソリューションの 1 つをサービス クラスに統合する必要がありますUpdate

于 2012-11-03T20:23:43.103 に答える