While revisiting some old code, I came across this workaround from a previous discussion. After testing, I can confirm that the behavior still persists in RavenDB 6.0.105.
Below is a complete test to demonstrate this.
'''
using Raven.Client.Documents.Queries;
using Raven.Embedded;
using Sparrow.Json.Parsing;
using System;
using System.Linq;
using Xunit;
public class UnitTest8_IDs
{
[Fact]
public void CollationTest()
{
EmbeddedServer.Instance.StartServer();
using var store = EmbeddedServer.Instance.GetDocumentStore("id-storage");
store.OnAfterConversionToDocument += (s, e) =>
string idParent = "EntityWithChild/1";
string idChild = "ChildEntity/1";
#region Create Entities
using (var session = store.OpenSession())
{
var child = new ChildEntity { Name = "Child", Id = idChild };
var parent = new EntityWithChild { Name = "Parent", ChildEntityId = child.Id, Id = idParent };
session.Store(child);
session.Store(parent);
session.SaveChanges();
Assert.Equal(idParent, parent.Id);
Assert.Equal(idChild, child.Id);
Assert.Equal(idChild, parent.ChildEntityId);
}
#endregion
#region Verify OnAfterConversionToDocument Workaround
using (var session = store.OpenSession())
{
var parentFromDb = (from parent in session.Query<EntityWithChild>()
let child = RavenQuery.Load<ChildEntity>(parent.ChildEntityId)
select new
{
Parent = parent,
Child = child
}).First();
Assert.Equal(idChild,
parentFromDb.Child.Id);
Assert.Equal(idParent,
parentFromDb.Parent.Id);
Assert.False(session.Advanced.WhatChanged().Any());
}
#endregion
#region WhatChanged shows Removed Property of "Id"
using (var session = store.OpenSession())
{
var parent = session.Load<EntityWithChild>(idParent);
var child = session.Load<ChildEntity>(idChild);
var whatChanged = session.Advanced.WhatChanged();
Assert.Equal(0, whatChanged.Count); // Fails, two entries with "RemovedField"
}
#endregion
}
class EntityWithChild : BaseEntity
{
public string Name { get; set; }
public string ChildEntityId { get; set; }
}
class ChildEntity : BaseEntity
{
public string Name { get; set; }
}
public abstract class BaseEntity
{
public string Id { get; set; }
protected BaseEntity()
{
Id = $"{GetCollectionName()}/{Guid.NewGuid()}";
}
protected virtual string GetCollectionName()
{
return GetType().Name;
}
}
}
'''