Check Your Relations
Nicolas Galler | October 17, 2010A familiar problem with upgrades from SalesLogix LAN to Web is many of the foreign keys may have some invalid values. The legacy LAN client allowed one to put basically anything in there without much validation since we were playing with raw SQL, but the NHibernate platform used in the new client is not as forgiving. Therefore you may find yourself with this type of errors:
System.Web.HttpUnhandledException: Exception of type ‘System.Web.HttpUnhandledException’ was thrown. —> System.Reflection.TargetInvocationException: Property accessor ‘Ticket’ on object ‘Sage.SalesLogix.Entities.TLXProjectExpense’ threw the following exception:’No row with the given identifier exists[Sage.SalesLogix.Entities.Ticket# ]‘ —> NHibernate.ObjectNotFoundException: No row with the given identifier exists[Sage.SalesLogix.Entities.Ticket# ]
What happened here is the original developer chose an empty string instead of a NULL to indicate the absence of a value – it works fine on the LAN client but the web client tries to actually load a ticket with an id of “ “. The solution recommended so far is to clean out those values as you find them… obviously not very practical in an upgrade where you could have dozens of foreign key relationships to check one by one.
Thankfully all the information we need to get around the problem is already stored by SalesLogix and collected in the entity model – so all we have to do in theory is crawl through the relationships defined in the App Architect and run an update for each one of them. It is actually quite easy as Sage prepared some neat (albeit undocumented) API to examine the model metadata. For example this is the code I used to load the project model and iterate through the relationships:
IProject project = ProjectUtility.InitProject(ModelPath); OrmModel model = project.Models.Get<OrmModel>(); foreach (OrmRelationship relationship in model.Relationships) { // ... }
It took me a few hours to write the app, mostly because I had set out to learn a few more things about WPF at the same time – the logic for the check and update itself was pretty easy. The one caveat is there are a few relationships that are a bit “odd” and can’t get fixed right (for example the M:1 relationship from targetresponse to MKTGSVC_RECIPIENT is on TargetResponseId which we can’t null out)
For now it is usable as a standalone app… Eventually I would like to make it as an App Architect extension and add a few features (most importantly the ability to drill down to see the actual data for the invalid records)
For the source code I made it available as part of the OpenSlx project on GitHub, but the binaries can be downloaded here if you want to give it a try (obviously be sure to backup the DB beforehand etc – the “no warranty” disclaimer is there for a reason!) One big caveat there before I forget – if you have problems with invalid Seccodeid in the Secrights table, etc, you may have to do some cleanup before and/or after running the script as it will null them out which will crash the client.





