エンティティフレームワーク5を使用するMVCアプリケーションがあります。エンティティを作成または更新するコードがいくつかありますが、更新されたデータに対して何らかの操作を実行する必要があります。これらの操作の中には、ナビゲーションプロパティへのアクセスが必要なものがあり、更新することができません。ここEntity Framework 5 - 変更を保存した直後にDbContextをリフレッシュする
は、例えば(私は簡略化コード)
モデル
class User : Model
{
public Guid Id { get; set; }
public string Name { get; set; }
}
class Car : Model
{
public Guid Id { get; set; }
public Guid DriverId { get; set; }
public virtual User Driver { get; set; }
[NotMapped]
public string DriverName
{
get { return this.Driver.Name; }
}
}
コントローラ
public CarController
{
public Create()
{
return this.View();
}
[HttpPost]
public Create(Car car)
{
if (this.ModelState.IsValid)
{
this.Context.Cars.Create(booking);
this.Context.SaveChanges();
// here I need to access some of the resolved nav properties
var test = booking.DriverName;
}
// error handling (I'm removing it in the example as it's not important)
}
}
は、上記の例では、作成方法のためのものであるが、私も持っています非常に似ているUpdateメソッドの同じ問題オブジェクトをGET
アクションでコンテキストから取り出し、Update
メソッドを使用してPOST
アクションに格納します。
public virtual void Create(TObject obj)
{
return this.DbSet.Add(obj);
}
public virtual void Update(TObject obj)
{
var currentEntry = this.DbSet.Find(obj.Id);
this.Context.Entry(currentEntry).CurrentValues.SetValues(obj);
currentEntry.LastModifiedDate = DateTime.Now;
}
は今、私はグーグルやスタックに見つかりましたが、何も私のために働いているように思わないいくつかの異なるアプローチを試みました。
私の最新の試みでは、SaveChanges
メソッドを呼び出してデータベースからデータを再クエリーした後、リロードを強制しようとしました。ここに私がしたことがあります。
私はすぐ後にすぐに私のHTTP
Create
とUpdate
でSaveChanges
呼び出しの後のコード行を追加することで、私は更新されたオブジェクトデータを取得しようとした
public int SaveChanges()
{
var rowsNumber = this.Context.SaveChanges();
var objectContext = ((IObjectContextAdapter)this.Context).ObjectContext;
objectContext.Refresh(RefreshMode.StoreWins, this.Context.Bookings);
return rowsNumber;
}
保存オブジェクトコンテキストをリフレッシュするSaveChanges
方法ovewriteましたアクション:
car = this.Context.Cars.Find(car.Id);
残念ながらナビゲーションプロパティはまだnull
です。データを変更した直後にDbContextを適切に更新するにはどうすればよいですか?私はもともと私が回避策を知っているが、それは醜いだと私はそれを好きではないことを言及するのを忘れ
EDIT
。ナビゲーションプロパティを使用するたびに、それがnull
であるかどうかを確認することができ、そうであれば手動で新しいDbContextを作成してデータを更新することができます。しかし、私は本当にこのようなハックを避けたいです。
class Car : Model
{
[NotMapped]
public string DriverName
{
get
{
if (this.Driver == null)
{
using (var context = new DbContext())
{
this.Driver = this.context.Users.Find(this.DriverId);
}
}
return this.Driver.Name;
}
}
}
を読み込みますか? 'this.Context.Cars.Find(id)'以外の元のオブジェクトも取得する必要がありますか? – RaYell
'Find'はデータベースからプロキシオブジェクトを返しますが、このトランザクション中にローカルに追加されたオブジェクトを見つけて更新すると、追加したオブジェクトが見つかります。 – qujck
私はあなたのソリューションに従ってみましたが、それは 'System.InvalidOperationExceptionにつながります:エンティティがコンテキスト内に存在しないため、タイプ 'Car'のエンティティに対してMember 'CurrentValues'を呼び出すことができません。コンテキストにエンティティを追加するには、DbSetのAddメソッドまたはAttachメソッドを呼び出します。 'this.Context.Set ().Attach(newEntry);を最初の行の直後に追加しました。 System.InvalidOperationException:プロパティ 'Id'はオブジェクトのキー情報の一部であり、変更することはできません。 ' –
RaYell