1

アップデート:

これは今私を夢中にさせています!

多くのグーグルなどの後、私は本当に解決策に近づいていません.....

ただし、さらに困惑していることが1つあります。それは、m_dbContext.SaveChanges()呼び出しの直前のエンティティの「状態」です。(完全なリポジトリコードについては、以下を参照してください)

var updateInfoState = m_dc.Entry(oldPage.UpdateInfo).State; // State is 'Modified'
var oldPageState = m_dc.Entry(oldPage).State;               // State is 'Detached' 

this.m_dc.SaveChanges();

「oldPage」が切り離されるのはなぜですか?

今はかなり必死になっています!! ;)

オリジナル:

EFコードに問題があるようです-最初に関連するテーブルを正しく更新します。

この簡略化された例では、「UpdateInfo」テーブルは新しいDateTimeで正常に更新されていますが、「Pages」テーブルは新しい「Name」値で更新されていません。

私はDropCreateDatabaseAlwaysを介してコードファーストPOCOをシードしています/Seedをオーバーライドします...そしてEFはテストテーブルを正しく作成しています-したがって、この時点でそれが何をしているのかを知っているようです...。

これは私が見逃している単純で明白なものだと確信しています!

すべてが非常に感謝しています!

私のクラスの定義:

public class Page
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual UpdateInfo UpdateInfo { get; set; }  // virtual For Lazy loading
}

[Table("UpdateInfo")]                                   // much better than EF's choice of UpdateInfoes! 
public class UpdateInfo
{
    public int Id { get; set; }
    public DateTime DateUpdated { get; set; }
}

public class DomainContext : DbContext
{
    public DbSet<Page> Pages { get; set; }
    public DbSet<UpdateInfo> UpdateInfo { get; set; }
}

Code-Firstによって作成されたテーブル

Pages Table
===========

    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](max) NULL,
    [UpdateInfo_Id] [int] NULL,

UpdateInfo Table
================

    [Id] [int] IDENTITY(1,1) NOT NULL,
    [DateUpdated] [datetime] NOT NULL,

私のリポジトリコード:

public Page Get(int id)
{
    Page page = m_dbContext.Pages.Single(p => p.Id == id);
    return page;
}

public void Update(PagePostModel model)
{
    Page oldPage = Get(model.PageModel.Id);                         // on oldPage Name = "Hello", DateUpdated = "Last Year"

    Page newPage = Mapper.Map<PageModel, Page>(model.PageModel);    // on newPage Name = "Goodbye"  (AutoMapper)
    newPage.UpdateInfo = oldPage.UpdateInfo;                        // take a copy of the old UpdateInfo since its not contained in the model

    newPage.UpdateInfo.DateUpdated = DateTime.UtcNow;               // update to now

    oldPage = newPage;                                              // copy the updated page we grabbed from dbContext above (NB Everything looks great here..oldPage is as expected)

    m_dbContext.SaveChanges();                                      // update - only the 'UpdateInfo' table is being updated - No change to 'Pages' table :(((
}
4

1 に答える 1

2

ご存知のように、EntityFrameworkには変更トラッカーAPIがあります。

データベースから取得したエンティティの変更を追跡するために、DbContextはその参照値を使用します。

上記の「更新」関数は、newPageをoldPageに挿入します。したがって、DbContextはoldPageがnewPageであることを認識しません。それで、それは「切り離された」です。

ただし、UpdateInfoの場合、これはoldPageの参照のコピーであるため、DbContextはその変更を追跡できます。したがって、「変更」されます。

この問題を解決するには、以下のコードを使用してみませんか?

Page newPage = Mapper.Map<PageModel, Page>(model.PageModel);
oldPage.UpdateInfo = newPage.UpdateInfo; 
oldPage.UpdateInfo.DateUpdated = DateTime.UtcNow;
m_dbContext.SaveChanges();

アップデート

次に、アタッチとデタッチのメソッドを使用します。

これらのメソッドは、DbContextからエンティティをアタッチおよびデタッチするのに役立ちます。

Page newPage = Mapper.Map<PageModel, Page>(model.PageModel);
// if you attach first, there will be an exception, 
// because there is two entities having same id.
m_dbContext.Entry(oldPage).State = EntityState.Detached; 
m_dbContext.Pages.Attach(newPage);
// if you don't set IsModified = true,
// DbContext cannot know it is changed.
m_dbContext.Entry(newPage).State = EntityState.Modified;
m_dbContext.SaveChanges();
于 2012-05-11T06:44:12.247 に答える