Closed dannief closed 2 years ago
This is the right place to post. Based on a quick look, this does look like a bug in our code. We think the problem stems from this line in the mapping:
entity.HasAlternateKey(e => new { e.BestPracticeId, e.Score });
We've never used HasAlternateKey
in our own applications which is why we haven't ever seen this problem. Within the framework we use an API function called GetKeys()
to find the key to build the url. However this method returns
both the primary and alternate key, so NakedObjects is then building a faulty key for the object.
I will flag this as a Bug for now and we will fix it for the next release. Meantime, to help you to get going again, I suggest you try temporarily commenting-out the alternate key from the mapping. Let us know if that does or doesn't fix the problem.
Removing the HasAlternateKey
produced the same error. I think this is due to EF introducing an alternate key by convention. See https://docs.microsoft.com/en-us/ef/core/modeling/keys?tabs=data-annotations#alternate-keys
Alternate keys are typically introduced for you when needed and you do not need to manually configure them. By convention, an alternate key is introduced for you when you identify a property which isn't the primary key as the target of a relationship.
Well if EF is introducing an alternate key by convention then the problem (from Naked Objects perspective) is essentially the same. I think we can safely say that at present NakedObjects does not work with alternate keys. It should be possible for us to fix this - we need to change the way we access the API such that we are just getting the primary key instead of all the keys.
In the meanitme ...
I am assuming that the reason you have not used the PK as the FK in an association is because you want to display to the user different_ 'identifiers' for associated objects in different contexts - is that correct? If so, I suggest you just use the object property, with no associated FK property (or with an FK property to the primary key, Hidden
from the user). Then add a derived (readonly
) property that displays the desired identifier from the associated object.
Or if you want the user to be able to change the associated object by editing the 'alternate' identifier then you could either:
(However, in either case, if the alternate identifier is relevant to the user I would have expected to see it used as, or within, the object's title).
Need to cherry-pick fix back to NO12/NF1
Stef has fixed the issue, and we have uploaded a new version of the NakedObjects.Server package (v12.0.1) to the Nuget public gallery. Please try this out and report back if it fixes your particular model.
Thank you. Will this issue be fixed in v13 beta as well soon? I am using the Template Server project downloaded from this repository, but that project is referencing v13 beta packages
v13.0.0-beta02 released with the fix. Please confirm back that it is now working for you.
I can confirm that navigation now works. However, I am getting an error if I change the the value of the child property and then save.
Error message received from server
Message: Object reference not set to an instance of an object.
Code: InternalServerError(500)
Description: A software error has occurred on the server.
Stack Trace :
at NakedFramework.Persistor.EFCore.Component.EFCoreLocalContext.<>c.<PreSave>b__43_5(INakedObjectAdapter no)
at System.Collections.Generic.List`1.ForEach(Action`1 action)
at NakedFramework.Persistor.EFCore.Component.EFCoreLocalContext.PreSave()
at NakedFramework.Persistor.EFCore.Component.EFCoreObjectStore.<>c.<PreSave>b__66_0(EFCoreLocalContext c)
at System.Array.ForEach[T](T[] array, Action`1 action)
at NakedFramework.Core.Util.CollectionUtils.ForEach[T](T[] toIterate, Action`1 action)
at NakedFramework.Persistor.EFCore.Component.EFCoreObjectStore.PreSave()
at NakedFramework.Persistor.EFCore.Component.EFCoreObjectStore.RecurseUntilAllChangesApplied(Int32 depth)
at NakedFramework.Persistor.EFCore.Component.EFCoreObjectStore.EndTransaction()
at NakedFramework.Core.Transaction.NestedTransaction.Commit()
at NakedFramework.Core.Component.TransactionManager.EndTransaction()
at NakedFramework.Facade.Impl.Impl.FrameworkFacade.End(Boolean success)
at NakedFramework.Rest.API.RestfulObjectsControllerBase.InitAndHandleErrors(Func`1 f)
Thanks. So we can look into this, can you clarify with a specific example of which property on which object you were changing and how you were saving it (I assume you were directly editing the object on screen and hitting Save rather than doing it through a method. Again, this is not an issue we have encountered so it may again be to do with the alternate keys, but we need to get to the bottom of it.
Yes. I was directly editing the object on screen and clicked Save. I edited the BestPracticeCriteriaScore property of the SystemBestPracticeScore. (This same child object is related to the parent using a foreign key that is not a primary key.) The domain object is Bounded, so a drop down list was generated on the UI. I selected another value and clicked Save
Thanks for clarification, Debbie-Ann. On the previous issue I stated that using Alternate Keys (with EF Core) was something we had little experience with, and it is clear that we haven't got to the bottom of it yet. I've added another ticket (#412) to warn anyone else about this area in general. I will try to contact you offline to discuss how best we can help you get going.
If this is not the right forum, please let me know. Any insight would be appreciated
The message on the UI is
And partial output from the server is:
The system seems to be passing the primary key (14) and the values used as the foreign key in the child object (4 and 1)
See information about the model below. Issue happens when navigating to the SystemBestPracticeScore.BestPracticeCriteriaScore property
The models are configured as below: