gpt4 book ai didi

c# - 将对象附加到 Telerik OpenAccess 数据上下文时遇到问题

转载 作者:太空宇宙 更新时间:2023-11-03 13:05:15 25 4
gpt4 key购买 nike

我正在编写一些测试来扩展基于 Telerik OpenAccess ORM 构建的库的存储库层,但在管理上下文时遇到了一些问题。

我正在创建一个新的 RegionEntity 对象并将其添加到数据库中。我使用 using 语句以便上下文自行清理。我还为添加的 RegionEntity 创建了一个分离副本,以便稍后可以将其重新附加到上下文。

    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。 (我已经删除了我的 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),因此该过程然后将实体附加到上下文并在第二次检查时我确认分离标志不再存在。

事实证明实体没有被附加......并且抛出了异常。

我已阅读有关将对象分离和附加到上下文的 Telerik 文档 ... Attaching and Detaching Objects

最佳答案

按设计 ObjectState是标志枚举,它包含构成数据访问持久状态的基本值和持久状态本身。

在这个枚举中,Detached是参与三个分离持久状态的值:DetachedCleanDetachedDirtyDetachedNew。您可以在 this article 中找到有关值和状态的更多信息。 .

当您从上下文中分离一个对象时,它的状态是DetachedClean。如果此时您更改任何属性,对象的状态将变为 DetachedDirty。如果您将对象附加回去,它将保持附加之前的状态。简单地说,附加对象的 Action 不会改变它的状态。

换句话说,检查 Detached是您获得“无法将实体附加到上下文”异常的原因。该值将始终在您的对象状态中可用。

当我向前阅读代码时,在这一行:

ctx.Delete(entityToRemove);

无论如何你都会得到一个异常,因为数据访问不允许你删除通过上下文的另一个实例检索到的对象。异常(exception)情况是:

InvalidOperationException:不允许两个不同对象范围之间的对象引用。

希望对您有所帮助。

-= 编辑 =-

当您将某个对象附加到上下文实例并调用 SaveChanges() 方法时,Data Access 将自动决定是在数据库中插入新行还是更新现有行。在这方面,插入和更新场景由 Attach/Detach API 处理。

关于删除场景,您有两种选择:

  1. 要从数据库中检索对象并通过 Delete() 方法将其删除(并调用 SaveChanges()),如下所示:

       var myObj = ctx.RegionEntities.First(r => r.Id == entityToRemove.Id);
    ctx.Delete(myObj);
    ctx.SaveChanges();
  2. 使用BulkDelete像这样的功能:

       var myObj = ctx.RegionEntities.Where(r => r.Id == entityToRemove.Id);
    int deletedObjects = myObj.DeleteAll();

对于第一个选项,您需要考虑的是在附加对象后是否调用 SaveChanges()。如果您希望在删除对象之前保留某些更改,那么这样做是个好主意。此外,当您使用上下文的 Delete() 方法时,您需要在处置上下文的当前实例之前通过 SaveChanges() 方法提交更改。如果不这样做,事务将被回滚,这意味着对象不会被删除。有关交易处理的详细信息,请参阅 here .

第二个选项,批量删除,在调用 DeleteAll() 方法时在单独的事务中执行删除操作。因此,任何其他未提交的更改都不会受到影响。然而,您需要考虑在附加对象后调用 SaveChanges(),尤其是当附加对象和删除对象是同一个对象时。

关于c# - 将对象附加到 Telerik OpenAccess 数据上下文时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30956541/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com