MarkDirty() question

MarkDirty() question

Old forum URL: forums.lhotka.net/forums/t/476.aspx


Massong posted on Tuesday, June 27, 2006

Hi,

I’ve ported an order line class from CSLA 1.x to CSLA 2.0.2 that uses a method to assign an article to this order line:

    Public Sub SetArticle(ByVal a As Article)
        mArticleID = a.ID
        mArticleName = a.Name
        mArticleNumber = a.Number

        MarkDirty()
    End Sub

When I call this method now my system hangs (I can’t move the mouse curser anymore) until I open the task manager. Afterwards I get a stack overflow exception in the Equals method of BusinessBase at calling GetIdValue().

All my GetIdValue()-methods just return a private member of type GUID:

    Protected Overrides Function GetIdValue() As Object
        Return mID
    End Function

Does the new MarkDirty() work differently to the old implementation? I figured out that I must call MarkDirty(True) to suppress the event to avoid the stack overflow exception. But the old MarkDirty() raises an event, too, doesn’t it?

Thanks,
Christian

ajj3085 replied on Tuesday, June 27, 2006

Have you tried stepping through your code and the Csla code to see what's going on?

Massong replied on Tuesday, June 27, 2006

Yes.

MarkDirty() raises the PropertyHasChangedEvent.
After that the Equals()-method of BusinessBase is called twice.
Then I jump into IEditableObject_CancelEdit() and then in Equals() again.
This goes on until the stack overflow exception is thrown.

It is difficult to step through the code, because the following COM-Exception is thrown when I’m to slow:

The CLR has been unable to transition from COM context 0x1a1b20 to COM context 0x1a1c90 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.

I’ve bound my collection of order lines to a TrueDatagrid and I think the grid causes the stack overflow exception when fetching the PropertyHasChanged event. Especially because it works when I use MarkDirty(True) to suppress the event. I can live with that, but I would like to know if the behaviour of MarkDirty() has changed in CSLA 2.x.

Thanks,
Christian

ajj3085 replied on Tuesday, June 27, 2006

Hmm... can you reproduce this error outside of the datagrid (using an nunit test or something similar)?  That would help rule out the data grid you're using.

I checked my source control (I'm keeping up to date by checking out Csla and the overlaying the updated source tree..this way i can easily track Csla changes) and MarkDirty hasn't changed since 2.0 RTM version (or even the beta for that matter).

If the problem persists while you're running your code outside the grid, it is likely your object.  Otherwise, I'd say the grid is behaving badly (I don't understand why its calling CancelEdit to begin with).  Did you override your Equals method?  What does your GetIdValue method look like? 

Andy

Massong replied on Wednesday, June 28, 2006

Hi.

Thanks for your efforts.

No, I can’t reproduce the error without the grid: I use my SetArticle-method outside of the grid together with a select-article-dialog and that works fine. The grid seems to fetch the PropertyChanged-event and try to find the changed row with help of the Equals()-method and so with GetIdValue(). When I had ported my class to CSLA 2.x I deleted the overridden Equals(), so I don’t have it overridden anymore. And my GetIdValue()-method just returns a private Guid member with my primary key:

    Protected Overrides Function GetIdValue() As Object
        Return mID
    End Function

I have no idea what the grid is doing with CancelEdit() because I don’t use Undo in this situation. If the user cancels editing I just close the window and the garbage collector throws the changed object away. Only if the user clicks the Save-button, I call ApplyEdit() and Save(). So I think it’s the grid. But the same grid worked fine with the CSLA 1.x implementation. I just must remember that I must call MarkDirty(True) in every situation, where I called MarkDirty() before and than it’ll work.

Overlaying the source tree with the different CSLA versions is a very good idea. I have my CSLA versions in different source safe projects, so it is not so easy to compare the files. I’ll give it a try.

Greetings,
Christian

 

ajj3085 replied on Wednesday, June 28, 2006

Well, I'm not quite sure what the problem would be.  Somehow the interaction of the grid and your code is causing an endless loop somewhere..

Can you post the full class by any chance?  It might be easier to spot the problem that way.

I think databinding in .Net 2.0 has changed quite a bit, so its not suprising that something is now going wrong.

Andy

Massong replied on Thursday, June 29, 2006

Thanks, but I will simply use MarkDirty(True) and additionally write on the ComponetOne support forum for the grid.

(I’m not sure if posting my class would help: we are a transport company and develop our software for our internal use only – so all variable names, methods, comments and other identifiers are in German… If you really want to go through this, …Wink [;)])

Greetings,
Christian

ajj3085 replied on Thursday, June 29, 2006

Yikes,

Well, posting the class may have helped, unfortunatly I don't know German.  I did learn Spanish in HS though, so I could possibly muddle through that.  Wink [;)]

Bonio replied on Sunday, September 10, 2006

Christian

Did you ever resolve this problem? I am running into similar issues with the C1 flexgrid and am stuck as to how to progress.

Thanks

 

Bonio

RanceDowner1234 replied on Tuesday, June 27, 2006

It might be a little too obvious but in your SetArticle it sets mArticleID but then your GetIDValue returns mID (which might be Nothing).

The way I do my GetIDValue( ) with a stock GUID is

Private _id As GUID = Guid.NewGuid
Protected Overrides Function GetIDValue( ) As Object
    Return _id
End Function

by setting the _id to a default I ensure it's never Nothing.


Massong replied on Wednesday, June 28, 2006

Hi.

Thanks for your reply. I have all my mIDs initialized with Guid.NewGuid. But I think a not initialized Guid would be Guid.Empty because of Guid is a value type with default constructor. I set mArticleID, because I don’t want to assign a complete Article-object to every order line. They have their own child collections and the overhead would be too big.
 
Greetings,
Christian

Copyright (c) Marimer LLC