6

Entity Framework 5 を使用する MVC アプリケーションがあります。いくつかの場所で、エンティティを作成または更新し、更新されたデータに対して何らかの操作を実行する必要があるコードがあります。これらの操作の一部では、ナビゲーション プロパティにアクセスする必要があり、それらを更新できません。

これが例です(私が持っている簡略化されたコード)

モデル

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

上記の例は Create メソッドのものですが、Update メソッドにも同じ問題があります。これは非常によく似ており、動作中のコンテキストからオブジェクトを取得し、動作中のメソッドをGET使用してそれを格納するだけです。UpdatePOST

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メソッドを呼び出してデータベースからデータを再クエリした後、リロードを強制しようとしました。これが私がやったことです。

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の呼び出しHTTP Createの直後に次のコード行を追加して、更新されたオブジェクト データを取得しようとしました。Update

car = this.Context.Cars.Find(car.Id);

残念ながら、ナビゲーション プロパティはまだnull. データを変更した直後に DbContext を適切に更新するにはどうすればよいですか?

編集

回避策を知っていることを最初に言うのを忘れていましたが、それは醜く、好きではありません。ナビゲーション プロパティを使用するときはいつでも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;
         }
    }
}
4

2 に答える 2

4

この問題はおそらく、コンテキストに追加しようとしている項目が、proxy遅延読み込みに必要なすべてのコンポーネントを備えていないことが原因です。SaveChanges()アイテムを呼び出した後でも、プロキシされたインスタンスに変換されません。

DbSet.Create() メソッドを使用して、ネットワーク経由で受け取ったエンティティからすべての値をコピーすることをお勧めします。

public virtual TObject Create(TObject obj)
{
    var newEntry = this.DbSet.Create();
    this.Context.Entry(newEntry).CurrentValues.SetValues(obj);
    return newEntry;
}

アップデート

SetValues()問題が発生している場合は、渡されたエンティティから作成されたプロキシにデータを転送してからAdd新しいプロキシ インスタンスをDbSet. このようなもの:

private bool mapCreated = false;
public virtual TObject Create(TObject obj)
{
    var newEntry = this.DbSet.Create();

    if (!mapCreated)
    {
        Mapper.CreateMap(obj.GetType(), newEntry.GetType());
        mapCreated = true;
    }
    newEntry = Mapper.Map(obj, newEntry);

    this.DbSet.Add(newEntry;
    return newEntry;
}
于 2013-07-05T11:09:19.983 に答える