Telerik OpenAccess ORM で構築されたライブラリのリポジトリ レイヤーを拡張するためのテストをいくつか書いていますが、Context の管理でいくつかの問題が発生しています。
新しい RegionEntity オブジェクトを作成し、データベースに追加しています。using ステートメントを使用して、コンテキストがそれ自体でクリーンアップされるようにします。さらに、追加された RegionEntity の Detached コピーを作成して、後でコンテキストに再アタッチできるようにします。
private RegionEntity AddTestRegionToTable()
{
String regionName = Guid.NewGuid().ToString();
RegionEntity newRegion = new RegionEntity () { /*...property assignment goes here ...*/ };
RegionEntity ret = null;
using (DbContext ctx = new DbContext())
{
ctx.Add(newRegion);
ctx.SaveChanges();
ret = ctx.CreateDetachedCopy<RegionEntity>(newRegion);
}
return ret;
}
これまでのところ...問題ありません。以下の TestMethod では、上記のメソッドを呼び出して、Detached RegionEntity を受け取ります。(私は自分の assert ステートメントを取り出しましたが、それらは問題にとって重要ではないためです)。次に、エンティティを、テストする Respository メソッドに渡します。
[TestMethod]
public void RemoveRegion_Success()
{
//
// Assemble
RegionEntity origEntity = AddTestRegionToTable();
//
// Act
deletedEntity = RegionRepository.RemoveEntity<RegionEntity>(origEntity);
//
// Assert
/* asserts go here */
}
完全を期すために、以下に残りのすべてのコードを、アプリケーションに表示されるとおりに含めます。リポジトリのメソッドは一般的です (繰り返しますが、この問題には関係ありません)。最初のメソッドは、テスト メソッドによって呼び出され、領域をentityToRemoveパラメーターとして渡すメソッドです。このメソッドは、DBUtils メソッドGetContext()を呼び出します。このメソッドは、エンティティから DbContext を取得するか、派生できない場合は、使用する新しいコンテキストを作成します。この例では、新しいコンテキストが作成されています。
public class RegionRepository
{
public static T RemoveEntity<T>(T entityToRemove) where T : class
{
T ret = null;
using (DbContext ctx = DbUtils.GetContext<T>(entityToRemove))
{
ret = RemoveEntity<T>(ctx, entityToRemove);
ctx.SaveChanges();
}
return ret;
}
public static T RemoveEntity<T>(DbContext ctx, T entityToRemove) where T : class
{
//
// first chcek to see if the listingToUpdate is attached to the context
ObjectState state = OpenAccessContext.PersistenceState.GetState(entityToRemove);
//
//If the object is detached then attach it
if (state.HasFlag(ObjectState.Detached))
{
ctx.AttachCopy<T>(entityToRemove);
}
//
// confirm that the DETACHED flag is no longer present.
ObjectState state2 = OpenAccessContext.PersistenceState.GetState(entityToRemove);
if (state2.HasFlag(ObjectState.Detached))
{
throw new Exception("Unable to attach entity to context");
}
ctx.Delete(entityToRemove);
return entityToRemove;
}
}
public class DBUtils
{
public static DbContext GetContext<T>(T entity)
{
DbContext ret = OpenAccessContextBase.GetContext(entity) as DbContext;
if(ret == null)
{
ret = new DbContext();
}
return ret;
}
}
とにかく、メソッドはこのコンテキストとエンティティをパラメーターとしてオーバーロードに渡します。このメソッドは、DbContext を追加のパラメーターとして受け取ります (複数ステップのワークフローで単一のコンテキストを使用できるようにします)。したがって、使用されるコンテキストは、エンティティから抽出したもの、またはGetContext()メソッドで作成したものである必要があります。次に、エンティティがコンテキストに関連付けられているかどうかを確認します。このシナリオでは、状態フラグ (その他はMaskLoaded | MaskManaged | MaskNoMask )の 1 つとして「Detached」のフラグを取得しているため、プロセスはエンティティをコンテキストにアタッチし、2 回目のチェックで Detached フラグが no であることを確認します。より長く存在します。
結局のところ、エンティティはアタッチされていません...そして例外がスローされています。
オブジェクトのデタッチとコンテキストへのアタッチに関する Telerik のドキュメントを読みました ...オブジェクトのアタッチとデタッチ