Adjust result builder to not return incomplete data from the entity store#8595
Adjust result builder to not return incomplete data from the entity store#8595N-Olbert wants to merge 2 commits intoChilliCream:mainfrom
Conversation
Adjusted first tests.
|
Hello @michaelstaib and @N-Olbert, what is the status of this branch? We are also suffering same issue, and I confirming that this fix is working. To hotfix it, we are generating the proejct with StrawberryShake, then copying the generated files, removing StrawberryShake dependency, and then adding the copied files to project normally. Then we are doing the adjustments using this fix. But this is not good way, too much manual effort and not a proper workflow. If something is missed in this branch, I can try to help in adding, but I am not knowing much of Git or GitHub as we are using SVN only |
|
Hi @TATA-VihaanJoni and thank you for your feedback. In the meantime, a less drastic hotfix could be to either:
|
Summary of the changes (Less than 80 chars)
Closes #5256 (in this specific format)
Closes #8290
Closes #8063
Probably also #5477
Background:
It was possible that Strawberry Shake returned incomplete data from the entity store when an entity referenced itself but each reference had a different selection set.
For example, consider this query:
Since the person is selfish, its best friend is him-/herself.
Because the entity store is filled recursively, the bestFriend selection set is evaluated first, writing
firstName,age, andphoneto the entity store for id"1". However, after that the selfishGuy selection set is evaluated and overwrites the entity store entry for"1"with the values ofid,firstName,lastName, and thebestFriend-id. As a resultageandphoneare lost.This PR fixes the issue by rechecking whether the entity is already present in the store after evaluating the arguments required to create the entity at the current hierarchy level. Therefore, no fields are lost and the entity store is filled correctly. In fact, it is populated step-by-step.
Core change (the args were inlined before):
if (session.CurrentSnapshot.TryGetEntity(entityId, out global::StrawberryShake.CodeGeneration.CSharp.Integration.RecursiveEntitySelfReference.State.PersonEntity? entity)) { var arg0 = Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")); var arg1 = Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "firstName")); var arg2 = Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "lastName")); var arg3 = Update_NonNullableIGetSelfishGuy_SelfishGuy_BestFriendEntity(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "bestFriend"), entityIds); var arg4 = Update_IGetSelfishGuy_SelfishGuy_FriendsEntityNonNullableArray(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "friends"), entityIds); session.SetEntity(entityId, new global::StrawberryShake.CodeGeneration.CSharp.Integration.RecursiveEntitySelfReference.State.PersonEntity(arg0, arg1, arg2, arg3, arg4, entity.Age, entity.Phone, entity.ZipCode)); } else { var arg0 = Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "id")); var arg1 = Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "firstName")); var arg2 = Deserialize_NonNullableString(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "lastName")); var arg3 = Update_NonNullableIGetSelfishGuy_SelfishGuy_BestFriendEntity(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "bestFriend"), entityIds); var arg4 = Update_IGetSelfishGuy_SelfishGuy_FriendsEntityNonNullableArray(session, global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "friends"), entityIds); + // Since arg3 or arg 4 may have changed the entity store, check again if the requested + // entity now exists (and if so, us it to merge the values like age, phone etc.) + if (session.CurrentSnapshot.TryGetEntity(entityId, out entity)) + { + session.SetEntity(entityId, new global::StrawberryShake.CodeGeneration.CSharp.Integration.RecursiveEntitySelfReference.State.PersonEntity(arg0, arg1, arg2, arg3, arg4, entity.Age, entity.Phone, entity.ZipCode)); + } + else + { session.SetEntity(entityId, new global::StrawberryShake.CodeGeneration.CSharp.Integration.RecursiveEntitySelfReference.State.PersonEntity(arg0, arg1, arg2, arg3, arg4, default !, default !, default !)); + } }