在多次缓存恢复/导入后,Dev Force导航属性出现问题

本文关键字:导航 Force Dev 属性 问题 缓存 恢复 导入 | 更新日期: 2023-09-27 18:09:41

我们在app中遇到了一个非常奇怪的问题我们实体上的导航属性最终变得"困惑"因为它不认为另一端有实体,而实际上有。导航属性是一对一导航我知道我们在过去遇到过一对一属性的其他问题所以也许我们只是遇到了一个奇怪的边缘情况错误?

在尝试以最简单的方式再现问题时,我发现我可以通过连续两次执行entityManager.CacheStateManager.RestoreCacheState(someCacheState)来再现它。做两次会导致问题,但做一次不会。在我们的应用程序中,我们正在恢复缓存状态,这似乎与问题有关。我不认为我们要修复它两次但也许我们是?不管怎样,这样做应该没问题吧?

同样,在我们的实际应用程序中,我可以通过在两个实体(参与一对一关系的两个实体)的列表上执行ImportEntities来重现问题两次。在这种情况下,我不需要做两次恢复相同缓存状态的奇怪事情来重现问题—我只需要Import两次。不幸的是,我无法在一个干净的解决方案中重现双重导入。

下面是一些示例代码,演示了预期的行为和实际的行为:

private static void TestMultipleImports()
{
    //Any database with a one-to-one should work.  I'm using Adventure Works here but I've modified 
    //    it to have a one-to-one relationship.  For each Contact there are 0 or 1 Contact Details
    //    (they both have ContactID as the Primary Key)
    var mainEm = new AdventureWorksEntities();
    //Add a Contact and a Contact Detail with the same SID
    var contact = new Contact {ContactID = 1};
    var detail = new ContactDetail {ContactID = 1};
    mainEm.AttachEntity(contact);
    mainEm.AttachEntity(detail);
    //DevForce correctly matched up the entities so navigating from Contact to Detail or 
    //  from Detail to Contact works as expected
    Assert.AreSame(detail, contact.ContactDetail);
    Assert.AreSame(contact, detail.Contact);
    //In another entity manager, add the same Contact and Details
    var altEm = new AdventureWorksEntities();
    altEm.AttachEntity(new ContactDetail {ContactID = 1});
    altEm.AttachEntity(new Contact {ContactID = 1});
    //Use our helper method to import everything from our alternate EM into the main one
    ImportAll(altEm, mainEm);
    //Verify the navigations are still working
    Assert.AreSame(contact, detail.Contact);
    Assert.AreSame(detail, contact.ContactDetail);
    //Now do a similar import except we'll import into the dummy EM before importing into the main EM.  
    //  This 'double import' seems to cause the problem.  It would also break if we imported twice into 
    //  main EM.
    var dummy = new EntityManager();
    ImportAll(altEm, dummy, mainEm, mainEm);
    //Verify once more.  This one will pass ...
    Assert.AreSame(contact, detail.Contact);
    //...but this will fail.  The Contact Detail is in the Entity Manager and it can navigate to its related
    //   Contact...but for some reason, the Contact can't navigate to the Detail any longer.  Instead of 
    //   being the expected Contact Detail entity, it is a Null Entity
    Assert.AreSame(detail, contact.ContactDetail);
}
//Perhaps a bit of an odd way to copy entities between entity managers but it seems like this should be a 
//   reasonable thing to do
private static void ImportAll(EntityManager source, params EntityManager[] destinations)
{
    var ecs1 = source.CacheStateManager.GetCacheState();
    foreach (var destination in destinations)
    {
        destination.CacheStateManager.RestoreCacheState(ecs1, RestoreStrategy.Normal);
    }
}

我们正在运行最新版本的Dev Force 2012: 7.2.3。

在多次缓存恢复/导入后,Dev Force导航属性出现问题

这里的潜在问题是DevForce如何在1:1关系中处理所谓的"未解决的父"实体的问题。多个导入/改变EntityCacheState问题主要是转移注意力,但确实暴露了问题。

我想我们已经解决了这个问题,但是如果可能的话,我们想让你得到测试版,以确保它解决了你的应用程序中的问题。请告诉我,我将为我们的ftp站点压缩包。

问题是EntityCacheState实际上会随着每次使用而变化,这会导致一些奇怪的边缘条件。

在您的测试用例中,您可能会注意到使用以下任何一种方法的良好结果:

  • 如果你在ImportAll
  • 的foreach循环中创建一个新的ECS
  • 如果您以与mainEm
  • 相同的顺序附加altEm实体

我知道实际应用中的问题与测试用例有些不同,但在7.2.4发布之前,您可以稍微调整一下代码作为解决方案。