This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
Normal 0 false false false EN-US X-NONE X-NONE MicrosoftInternetExplorer4 /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman","serif";} I am getting a stack overflow in the same function that was giving me the circular reference once I remove the circular reference. Is this something you want me to post on the forums or send to you directly? Basically I have a unit test for my new generic Depot code, to test finding an object using a key for an entity that has multiple keys as part of a composite key. So the function I am calling is this: ProductDescription description = MultiKeyDepot.Find(new ProductDescriptionId(1, 1775)); The find function is written like this (it works just fine with a single integer key): public TEntity Find( The exception details are slim because the stack overflowed so VS is not able to work out the call stack. I will send you the model and my small test database via email. |
|
|
Hmm, looks like a bunch of style junk came over when I cut/pasted from Outlook. Is there a way to edit a post and fix that up? |
|
|
Ok, I have found what I think is the bug stopping models where you have levels of circular references causing an infinite loop and hence a stack overflow. I am not entirely sure, but I think it is related to my BackOrder class, which is mapped to the Order class through two associations. There is the regular association based on the orders_id in that table, which associates the back order with a particular order. But we have another foreign key in that table called ‘shipped_in_order’ (not sure why they left the _id off on that field), which is the ID of the order the back order was eventually shipped in. I think that is where the circular reference comes from, because it would appear that when it visits the Customer node, it ends up drilling down into the BackOrder node, which drills into the OrderNode, which then has an association back to the Customer node in it (since each order is associated with a customer). So I think the circular reference is that we for every Customer, there is a set of Orders. For every order there is a set of BackOrders, and for every BackOrder there is an associated ‘ShippedInOrder’. Which gets back to the Order record, which then somehow goes back to the Customer entity. And the whole things starts all over again. I made one simple change to the code and now I don’t get the stack overflow and the LINQ appears to be working. Specifically I moved the ‘MarkVisited’ call at line 62 in TopologicalSort.cs up to line 43. Basically moving it above the loop that visits all the entities through associations. Clearly if you need to be able to handle some kind of circular reference, you have to mark the node you are ‘visiting’ as visited before you visit any associations, otherwise when you hit that node again as you drill into the associations, you are going to just keep on looping all over again. It would seem that if there are NO circular references, it would never iterate over the same entity again, so it makes no difference if you mark the entity as visited before or after you process all the associations. But if there is a chance it will end up hitting itself again, the you do need to mark it visited first. I can't claim to know the code well at all (just looked at it a few hours ago), but it would seem logical to me that you can simply mark the node as visited before you process the associations? Perhaps that would even solve the problem of my original circular reference that I had to take out, because there is code in that same function that checks for it (but it just seems to check for a circular reference back to itself from one level deep I think). I will send Ivan the code changes I have made to get his feedback (not sure he wants me posting code on the forums)? |
|
|
Thanks for the info. Unfortunately the proposed fix doesn't work -- it can result in an incorrect sort order which causes foreign key integrity errors on databases that have them (I think you're using MyISAM so the errors wouldn't have manifested in your tests). The underlying problem is that you have a circular relationship between Order, OrderValidationTracking and TelephoneCallback. Order has a foreign key to OrderValidationTracking; OrderValidationTracking has a foreign key to TelephoneCallback; and TelephoneCallback has a foreign key to Order. This means LightSpeed can't determine a safe order in which to perform inserts or deletes. It wants to insert Orders before TCBs, so that any foreign keys required by TCB will be in place when it does the TCB insert; similarly it wants to insert TCBs before OVTs; and finally it wants to insert OVTs before Orders. (Again, because you're using MyISAM, the database doesn't actually check whether foreign keys are valid; but LightSpeed doesn't know that.) Obviously we have a bug in that it is crashing with a stack overflow instead of reporting a circular association error, and we'll get you a fix for this; but the underlying issue is that you'll need to look at breaking the circular dependency in your model. |
|
|
Ok thanks. If you can find a way to flag this so I know where the problems lie I can fix my model, although flagging it might be expensive to be honest; but I assume this is only done once on the model and not all the time?
|
|
|
I am not sure I fully understand why you cannot determine the save order for an entity when you save it if there is a circular reference? This works in Entiyt Framework (and OpenAccess), so I would assume the root of the graph would be the entity you request to save? So if I ask to save an Order entity, it would know that is the root of the graph? Or if I create a new TelephoneCallback and ask to save it, that would be considered the root of the graph? We are having a hard time restructuring the database schema to match this limitation. |
|
|
Except that you don't save an entity: you save a unit of work. There is no root. The solution may be to keep the existing schema but break one of the associations in LightSpeed -- keep the foreign key field, but remove the EntityHolder/EntityCollection pairing. It is the latter which LightSpeed uses the sort order, so removing them removes the circularity. You can of course still have properties or methods to provide an entity-centric way of working with the FK e.g. partial class Order { partial class OVT { (You could make these properties with getters and setters; I used methods because this reminds me that the associations are not managed by LightSpeed, which is important because it means they cannot be traversed in queries, will not be cascade deleted, etc.) |
|
|
Yes, that makes sense. I will try that for now. Perhaps in the future there would be way to have an association in the designer, but somehow mark that it should not be traversed when you build the topological (ie: some kind of reference only association?). |
|
|
I noticed that the TelephoneCallback entity also has a customers_id foriegn key as well, which links back to the customer who placed the order. Won't that also cause the same problem, because it will go from the Customer entity, to the Order entity, to the OrderValidationTracking to the TelephoneCallback and then back to Customer? |
|
|
Hmm, not sure. That would mean Order has a FK to OVT, OVT has a FK to TCB, and TCB has a FK to Customer. But I am guessing that Customer does NOT have a FK to Order; rather Order has a FK to Customer (because an Order is for one Customer but a Customer could have many Orders). If that is correct then the relationship is not circular -- rather, there are two parallel chains -- and it should be fine. |
|
|
Right, you are correct. I think I get it better now :) |
|
|
I've now committed an update which will provide a bit more diagnostic information if LightSpeed detects an indirect circular reference. It is a bit kludgy but should at least provide a meaningful exception instead of a stack overflow. This will be included in future nightly builds. |
|
|
Ok thanks, I will give it a shot. Has the designer been updated for 1:1 mappings? |
|
|
The designer has not been updated yet, but I will try to get it done today. |
|