我正在编写一些测试来扩展基于 Telerik OpenAccess ORM 构建的库的存储库层,并且在管理上下文时遇到了一些问题。
我正在创建一个新的 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 中,我调用上述方法并收到一个分离的 RegionEntity。(我已经撤回了我的断言声明,因为它们与问题无关紧要)。然后我将实体传递给我想要测试的 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),因此该过程随后将实体附加到上下文,并在第二次检查时确认已分离标志为否存在时间更长。
事实证明,实体没有被附加......并且正在引发异常。
我已阅读有关分离和附加对象到上下文的 Telerik 文档...附加和分离对象