为什么这段代码(尝试)用第二个对象覆盖我的第一个对象?我的第一个对象专门有一个ID为" StringBasedIdClasses / 1",而第二个对象没有提供Id,所以Raven应该生成一个未使用的Id不应该呢?
var quickStore = new EmbeddableDocumentStore() { RunInMemory = true };
quickStore.Initialize();
quickStore.RegisterListener(new DocumentConversionListener()).RegisterListener(new DocumentStoreListener());
using (var session = quickStore.OpenSession())
{
session.Advanced.UseOptimisticConcurrency = true;
var stringIdTest = new StringBasedIdClass()
{
Id = "StringBasedIdClasses/1",
Name = "StringItem1"
};
session.Store(stringIdTest);
session.SaveChanges();
}
using (var session = quickStore.OpenSession())
{
session.Advanced.UseOptimisticConcurrency = true;
var stringIdTest = new StringBasedIdClass()
{
Name = "DidIReplaceYou"
};
session.Store(stringIdTest);
session.SaveChanges();//This fails with a ConcurrencyViolation as I use OptimisticConcurrency and have Etag support on my objects
}
一切都在使用文档存储的一个当前实例。这似乎很基本,所以一定要错过一些简单的东西。
答案 0 :(得分:7)
好的,答案部分是托马斯所说的,但更具体地说,RavenDb完全忽略了你手动插入的ID。为了进行批量导入(比如从旧系统到新系统的数据迁移,我需要执行以下操作:
在导入结束时,使用以下代码将集合的hilo(基本上是新ID的起点)设置为高于系统中现在最高ID的值:
session.Store(new {Id = "Raven/Hilo/{yourcollectionname}", Max = newMaxValue});
session.SaveChanges();
现在初始化新商店时,将使用正确的hilo值。
请注意,使用内存版本的EmbeddableDocumentStore
无法模拟此过程,因为您每次打开商店时实际上都会创建一个全新的服务器实例。因此,如果您尝试使用现有/非现有记录的已知ID进行集成测试,则必须让Raven选择ID而不将它们设置在您自己的对象中。这应该可以正常工作,因为你的新内存存储总是从1开始。为确保隔离我的测试,我为每次测试开了一个新商店。
答案 1 :(得分:2)
RavenDB的HiLo密钥生成器并不知道StringBasedIdClasses/1
已在使用中,因此它会将其分配给您的第二个文档。有关详细信息,请参阅Document IDs generation strategies。