﻿<?xml version='1.0' encoding='UTF-8'?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>CapableObjects Forums / ECO / General discussions  / Recommendation needed how to implement a special delete behaviour / Latest Posts</title><generator>InstantForum.NET v4.1.4</generator><description>CapableObjects Forums</description><link>http://www.capableobjects.com/apps/InstantForum414/</link><webMaster>forums@capableobjects.com</webMaster><lastBuildDate>Wed, 08 Feb 2012 22:44:12 GMT</lastBuildDate><ttl>20</ttl><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>Got some advice (thanks Demitry) and through a little Eco magic, and some of my own, I have removed the timer crap from the sample. A new and improved sample is now attached.&lt;/P&gt;&lt;P&gt;I didn't add many comments and there may be a need to use Weak References that I have not explored yet - the way I did it I htink they might not be necessary.(?)&lt;/P&gt;&lt;P&gt;Enjoy...</description><pubDate>Fri, 12 Mar 2010 03:31:15 GMT</pubDate><dc:creator>RickWeyrauch</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>Here is my IDataErrorInfo wrapper stuff for Eco. The sample project is fairly cheesey because I was just slapping a simple view to show the object in error and some quick and dirty ways to make it happy. Add a line and see if you can make it error free - if you can the Constrained Save button will come on.&lt;/P&gt;&lt;P&gt;There is one thing I am really not happy with but just could not figure out how to do better and still get this in tonight. I am using a timer event to fire running the dirty objects and test their Constraints because I could not find an Event in any of the Eco services that fired everytime any attribute or association changes on any object. I kind of concluded that there may have never been a request by anyone to get that - and I didn't want to take the time to add my own object by object watcher. Maybe I just missed it and someone can tell me about a way to do this. I guess I also assume that a stack of subscriptions would do the trick but again that is more than I wanted to do for this sample.&lt;/P&gt;&lt;P&gt;Also, the Command wrapper I have is all WPF specific so I will have to make a WPF sample to show how that works.</description><pubDate>Wed, 10 Mar 2010 03:59:05 GMT</pubDate><dc:creator>RickWeyrauch</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>I will add my Command to Eco binding classes in the sample I am putting together. It really shines for connecting WBF buttons to Eco State Triggers.&lt;/P&gt;&lt;P&gt;Right now the sample is over at C.O. getting "looked at" for a little issue I had with it. As soon as we can resovel the issues I will post the sample here.</description><pubDate>Mon, 08 Mar 2010 18:03:37 GMT</pubDate><dc:creator>RickWeyrauch</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>All you mention should belong to application logic that handles the wrong inputs of user, listens to events in buisiness logic, accomplishes conversion-stuff in Databinding (in WPF for ex.) and so on. Specially in WPF the MVVM pattern is here that stuff. Also the Commands implementation - it is also the matter of application layer, not the business logic, because it can differ from app to app whether you can edit an object or not, think about priviledges for ex.&lt;/P&gt;&lt;P&gt;The only consideration of using constraint logic on the model level for me is multi-client architecture - it is because you can never be sure your data are correct indeed before you save these in DB.</description><pubDate>Mon, 08 Mar 2010 11:12:27 GMT</pubDate><dc:creator>efim</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>You cannot prevent a user from entering invalid data in a control by coding the rules in the model. No matter what you do in the model, the user can still enter invalid data into a text box. Either you let them move on giving them an error on the text box control or you prevent them from leaving the control until they correct the problem. The later is very burdensome or might be impossible for the user to do. So I choose to do the former and allow the user to leave the control but give them an error indicating something is wrong. The IDataErrorInfo does this for you automatically. &lt;P style="MARGIN-BOTTOM: 0in"&gt;&lt;BR&gt;&lt;/P&gt;&lt;P style="MARGIN-BOTTOM: 0in"&gt;If it is possible to keep a user from entering into an error condition by disabling a button or control, I will do so explicitly in the form. The prevention logic is different from the constraint logic. The constraint logic indicates an error condition exists. Whereas the prevention logic indicates that an action/command will cause an error condition. A robust application needs both.&lt;/P&gt;&lt;P style="MARGIN-BOTTOM: 0in"&gt;&lt;BR&gt;&lt;/P&gt;&lt;P style="MARGIN-BOTTOM: 0in"&gt;WPF has a nice concept where commands call a CanExecute method to determine if the command can be executed. The logic that determines the CanExecute should be programmed in the domain object. So the CanExecute event code should call into the domain object to determine the result. &lt;/P&gt;&lt;P style="MARGIN-BOTTOM: 0in"&gt;&lt;BR&gt;&lt;/P&gt;&lt;P style="MARGIN-BOTTOM: 0in"&gt;It would be very nice if we could bind the wpf commands to the eco domain object. Rick has done some things interesting things to accomplish this. Maybe he could chime in. :)&lt;/P&gt;&lt;P style="MARGIN-BOTTOM: 0in"&gt;&lt;BR&gt;&lt;/P&gt;&lt;P style="MARGIN-BOTTOM: 0in"&gt;Brian</description><pubDate>Sun, 07 Mar 2010 20:39:58 GMT</pubDate><dc:creator>brian</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>[quote][b]brian (2010-03-05)[/b][hr]&lt;P class=MsoNormal style="BACKGROUND: white; MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: #1f5080; FONT-FAMILY: Verdana"&gt;For your specific situation I would enforce the business rule with IDataErrorInfo methodology and also put a check on the user interface to disable the delete button when there is only one record in the detail.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P class=MsoNormal style="BACKGROUND: white; MARGIN: 0in 0in 0pt"&gt;.[/quote]&lt;/P&gt;&lt;P class=MsoNormal style="BACKGROUND: white; MARGIN: 0in 0in 0pt"&gt; &lt;/P&gt;&lt;P class=MsoNormal style="BACKGROUND: white; MARGIN: 0in 0in 0pt"&gt;I had a look into IDataErrorInfo and must admit I'm not much impressed;-)&lt;/P&gt;&lt;P class=MsoNormal style="BACKGROUND: white; MARGIN: 0in 0in 0pt"&gt;Quite simple - yes, but I guess suites for realtively simple validation cases one instance (property)&lt;/P&gt;&lt;P class=MsoNormal style="BACKGROUND: white; MARGIN: 0in 0in 0pt"&gt; &amp;lt;-&amp;gt; one possible problem. In any other case the information get lost when you e.g. concat 2 or more error messages in one string, not talking about other exception data as number, inner exception and so on. But the main problem with this approach, not specially concerning IDataErrorInfo is  that you need some smart decision rools that should be able to leave an invalid state and go to some reasonable valid one. The Undo is not necessary always the best choice as it can lead to deadlocks. &lt;/P&gt;&lt;P class=MsoNormal style="BACKGROUND: white; MARGIN: 0in 0in 0pt"&gt;I can agree if an invalid state is entered in an UI in "Idle"-state, your decision rule could be (and Is in most cases) a User that is smart enough to find the best choice. But what if not? That is why  I used not to allow invalid states in an application in general, but rather to take care about always valid transitions between states. &lt;/P&gt;&lt;P class=MsoNormal style="BACKGROUND: white; MARGIN: 0in 0in 0pt"&gt;It is better not to do sins than later regret and try to correct these isn't it?;-)</description><pubDate>Sat, 06 Mar 2010 23:51:43 GMT</pubDate><dc:creator>efim</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>[quote][b]Peter Morris (2010-03-05)[/b In the case where you need two dates (for example) to always be in sync even before persisting you can make their setters private and have a method which sets both dates at the same time.&lt;BR&gt;[/quote]&lt;/P&gt;&lt;P&gt;Exactly this solution I would prefer no matter with persistance or not because it would give guarantee the object space is always in valid state.&lt;/P&gt;&lt;P&gt;[quote][b]Peter Morris (2010-03-05)[/b&lt;BR&gt; your problem IS a persistence problem.[/quote]&lt;/P&gt;&lt;P&gt;It would be in a multi-client environment, but for single-client I make logically no difference between persisted and not (yet) persisted object. Why should I do?</description><pubDate>Sat, 06 Mar 2010 23:14:58 GMT</pubDate><dc:creator>efim</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>The value in Modlr doing it natively is that bad OCL will be found via the Verify Model checks. It is the same argument for why the View Models being incorporated directly by C.O. in Modlr is so valuable. I need pre-runtime (and preferably compile time but I will take any pre-runtime) validation of my OCL. If it does not break until runtime, then the OCL is a liability == to it's assest.&lt;/P&gt;&lt;P&gt;Maybe that would be another good feature idea...... A call back interface on Verify Model where the application developer can say whether or not any non-Modlr OCL is still valid against the current model. Then, if I make some fancy-schmancy OCL based extension, I have an opportunity to run it against the model. Of course, I could make such a thing now but this callback would (should, could) have an IVerifyOclService that is already pointing at the model environment (Eco must have it for it self to verify OCL) that I could just toss my OCL at so that I do not have to do all the work of getting a "Verify the Model" environment setup.&lt;/P&gt;&lt;P&gt;Capable Objects - Aren't you glad I am back on the Eco bandwagon? Three new feature request a week! The problem is, it is so easy to love that I just want to love it to death!!!</description><pubDate>Fri, 05 Mar 2010 13:53:00 GMT</pubDate><dc:creator>RickWeyrauch</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>[quote][b]RickWeyrauch (2010-03-05)[/b][hr]...&lt;br&gt;The missing feature is Property Constraints. Inside the Eco model, each property actually has a Constraint collection but the modlr does not provide any access to it. I ended up using the Tag Properties collection to store them. Work fine but there is no pre-runtime way to validate your OCL.[/quote]&lt;br&gt;I just provide two implementations of my own IConstraint interface - one for the modelled constraints (holds IExpression) and another for the property "constraints" (holds IProperty). I add property constraints only if: // pseudo C# code follows&lt;br&gt;ValueForTag("Eco.AllowNULL", "False") == "False" &amp;&amp; ValueForTag("Eco.AsNullable", "False") == "False" &amp;&amp; PropertyInfo.PropertyType is nullableType .&lt;br&gt;&lt;br&gt;I agree that property constraints (not null) needs several checks, which is strange.&lt;br&gt;</description><pubDate>Fri, 05 Mar 2010 10:55:51 GMT</pubDate><dc:creator>Pawel</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>[quote][b]efim (2010-03-03)[/b][hr]I can't agree with the validation point "update database". It would mean only the objects in database are valid, but what if these are not yet saved andthe user rely on the valid state? Normally an invariant should be validated after each publicmethod call, not only Update DB, because of that I don't like invariants.[/quote]&lt;br&gt;&lt;br&gt;In the case where you need two dates (for example) to always be in sync even before persisting you can make their setters private and have a method which sets both dates at the same time.  But that is beside the point really, your problem IS a persistence problem.</description><pubDate>Fri, 05 Mar 2010 09:39:38 GMT</pubDate><dc:creator>Peter Morris</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>I suppose I should get off my but and make a post with my IDataErrorInfo Eco wrapping classes. I have a very nice class that runs the constraints and post the broken ones via the interface. The biggest reason I never did post it is that it si not really done the way we would want it due to a missing feature (see below) in the Eco Modlr but it is actually very usable the way it is and so I will make a new project, port the wrapper classes over to it and then post it. Look for it soon....&lt;/P&gt;&lt;P&gt;The missing feature is Property Constraints. Inside the Eco model, each property actually has a Constraint collection but the modlr does not provide any access to it. I ended up using the Tag Properties collection to store them. Work fine but there is no pre-runtime way to validate your OCL.</description><pubDate>Fri, 05 Mar 2010 03:20:59 GMT</pubDate><dc:creator>RickWeyrauch</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>&lt;P style="MARGIN: 0in 0in 0pt; BACKGROUND: white" class=MsoNormal&gt;&lt;FONT color=#000000 size=3 face="Times New Roman"&gt;[quote][b]efim (2010-03-04)[/b][hr]I avoid constraints whenever possible because they cry after something bad happened. I need then some means to go back to a valid state, and it is not always good if user should do it.&lt;/FONT&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;[/quote]&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; BACKGROUND: white" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;I used to try to implement business rules / constraints on setters so the domain objects remained constrained, but I realized it was just impractical to do.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;I found the IDataErrorInfo interface in .NET and decided this was the way to enforce my business rules.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;The methodology is to allow your objects to be in error but to have a standard way to communicate the errors.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;You always know if a domain object is valid by using the interface on the object.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;If the user gets into an error state that cannot be resolved, Eco provides nice undo features to rollback changes to a valid state.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;If you never allow invalid objects to be saved, you are guaranteed to have valid objects stored in the server.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; BACKGROUND: white" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; BACKGROUND: white" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;For your specific situation I would enforce the business rule with IDataErrorInfo methodology and also put a check on the user interface to disable the delete button when there is only one record in the detail.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; BACKGROUND: white" class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT color=#000000 size=3 face="Times New Roman"&gt; &lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; BACKGROUND: white" class=MsoNormal&gt;&lt;FONT color=#000000 size=3 face="Times New Roman"&gt;[quote][b]efim (2010-03-04)[/b][hr] BTW, thank you for the tip to use IDataError. I didn't closely use it before. I don't want however to use too specific .Net features in the business logic layer, because it belongs closer to PIM and it can be more difficult to migrate it in the future to other platforms.&lt;/FONT&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;[/quote]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; BACKGROUND: white" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;One of the beauties of the IDataErrorInfo interface is that it is very simple.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;It would be very easy to port to any platform.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; BACKGROUND: white" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; BACKGROUND: white" class=MsoNormal&gt;&lt;FONT color=#000000 size=3 face="Times New Roman"&gt;[quote][b]efim (2010-03-04)[/b][hr]&lt;/FONT&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt; &lt;/SPAN&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-FAMILY: Verdana; FONT-SIZE: 10pt"&gt;I don't understand in what concern throwing exception can be problem for data binding&lt;/SPAN&gt;&lt;FONT size=3 face="Times New Roman"&gt;.&lt;/FONT&gt;&lt;/FONT&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;[/quote]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; BACKGROUND: white" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;In winforms an exception that is thrown during a data-bind setter operation is eaten by the data binding framework.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;No error is thrown and the user cannot leave the control the error occurred in.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;I think WPF has similar behavior.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; BACKGROUND: white" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; BACKGROUND: white" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;Brian&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;P&gt;.</description><pubDate>Fri, 05 Mar 2010 01:02:57 GMT</pubDate><dc:creator>brian</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>Hi Brian,&lt;/P&gt;&lt;P&gt;I avoid constraints whenever possible because they cry after something bad happened. I need then some means to go back to a valid state, and it is not always good if user should do it. I avoid user interactions in business logic concerns whenever possible. I certainly understand there are scenarios where it is inevitable or preferrable. Perhaps Peter's example is one of them.&lt;/P&gt;&lt;P&gt;Meanwhile I imagine a suitable solution for my case. I would implement cascade deletion by myself, all in an in-memotry transaction (pseudocode):&lt;/P&gt;&lt;P&gt;class A&lt;/P&gt;&lt;P&gt;void Predelete() { &lt;/P&gt;&lt;P&gt;try&lt;/P&gt;&lt;P&gt;  Begin Transaction;&lt;/P&gt;&lt;P&gt;  this.IsAboutToDelete = true;&lt;/P&gt;&lt;P&gt;  &amp;lt;Delete subitems of B&amp;gt;&lt;/P&gt;&lt;P&gt;  commit&lt;/P&gt;&lt;P&gt;except&lt;/P&gt;&lt;P&gt;  rollback&lt;/P&gt;&lt;P&gt;  this.IsAboutToDelete = false;&lt;/P&gt;&lt;P&gt;end &lt;/P&gt;&lt;P&gt;This way I guarantee always valid state of the model.&lt;/P&gt;&lt;P&gt;BTW, thank you for the tip to use IDataError. I didn't closely use it before. I don't want however to use too specific .Net features in the business logic layer, because it belongs closer to PIM and it can be more difficult to migrate it in the future to other platforms. &lt;/P&gt;&lt;P&gt;I don't understand in what concern throwing exception can be problem for data binding?&lt;/P&gt;&lt;P&gt;}</description><pubDate>Thu, 04 Mar 2010 11:41:29 GMT</pubDate><dc:creator>efim</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>[quote][b]efim (2010-03-03)[/b][hr]I can't agree with the validation point "update database". It would mean only the objects in database are valid, but what if these are not yet saved and the user rely on the valid state? Normally an  invariant should be validated after each public method call, not only Update DB, because of that I don't like invariants.[/quote]&lt;/P&gt;&lt;P&gt;If you display the invalid state / errors to the user, the user would know not to rely on the state.  If you implement Peter's example of enforcing a start date to be before an end date by thowing an exception, you will have many problems.  Not only will you put undo constraints on the user's work flow, but you will not be able to use data binding on your forms.  I know it will not work in Winforms.  I don't think it will work in WPF either.  It might work in ASP.NET because data binding occurs on a form submit rather than granularly for each property.&lt;/P&gt;&lt;P&gt;Brian</description><pubDate>Wed, 03 Mar 2010 22:39:40 GMT</pubDate><dc:creator>brian</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>I can't agree with the validation point "update database". It would mean only the objects in database are valid, but what if these are not yet saved and the user rely on the valid state? Normally an  invariant should be validated after each public method call, not only Update DB, because of that I don't like invariants.</description><pubDate>Wed, 03 Mar 2010 16:37:32 GMT</pubDate><dc:creator>efim</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>[quote][b]efim (2010-02-26)[/b][hr]please don't come with constraints: I avoid them in general[/quote]&lt;br&gt;&lt;br&gt;And that's the problem :-)&lt;br&gt;&lt;br&gt;You are putting the invariant checking on the property level, which is not really the best way to do it.  For example if you had a class with StartDate and EndDate, and on the properties you enforced an invariant that EndDate &amp;gt;= StartDate then you always have to do this&lt;br&gt;&lt;br&gt;Then you will have to write code like this to ensure you don't throw an exception&lt;br&gt;EndDate = SomeEndDate;&lt;br&gt;StartDate = SomeStartDate;&lt;br&gt;&lt;br&gt;and then when you want to move the dates earlier you would have to do this to ensure you don't throw the exception&lt;br&gt;StartDate = NewStartDate;&lt;br&gt;EndDate = NewEndDate;&lt;br&gt;&lt;br&gt;and to move the dates later you would have to do&lt;br&gt;EndDate = NewEndDate;&lt;br&gt;StartDate = NewStartDate;&lt;br&gt;&lt;br&gt;Basically you are forcing the user to enter data in a specific order, in this case the user of your class is more code but it could be a user interface.  You wouldn't write code like that, would you?  I hope not!&lt;br&gt;&lt;br&gt;But that is what you are doing here.  What you should do is to put constraints on the "A" class and make sure that your EcoSpace always validates objects before performing an UpdateDatabase.  That would solve your problem immediately and save you from encountering other similar problems in the future.&lt;br&gt;</description><pubDate>Tue, 02 Mar 2010 12:31:25 GMT</pubDate><dc:creator>Peter Morris</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>It takes a little bit of explaining, but here is an alternative approach.&lt;P style="BACKGROUND: white"&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;One of the nicest interfaces in .NET is the IDataErrorInfo.  It is a rather simple interface, but what it provides is enormous.  It basically provides an interface for communicating errors between bound objects and controls on a form.  Winforms and WPF controls use this interface if the object bound to implements it.  Unfortunately, ASP.NET does not, but you can create your own validators to do so.  That is what I have done.&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="BACKGROUND: white"&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;I implement most of my business rules/constraints in IDataErrorInfo's indexer property.  I do this by implementing the interface on a base class for all my eco objects and overriding behavior subclasses.  I create a virtual GetPropertyError method that subclasses override to check for errors.  I have used this interface this way in past non-eco projects with great success.  From my current eco project I'm working on, here is the base class implementation (note, it is not completely finished yet):&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;        &lt;/SPAN&gt;#region&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt; IDataErrorInfo&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;        &lt;/SPAN&gt;[&lt;/FONT&gt;&lt;SPAN style="COLOR: #2b91af"&gt;XmlIgnore&lt;/SPAN&gt;&lt;FONT color=#000000&gt;]&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;        &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IDataErrorInfo&lt;/SPAN&gt;&lt;FONT color=#000000&gt;.Error { &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;&lt;FONT color=#000000&gt; { &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt;&lt;FONT color=#000000&gt;(GetErrors()); } }&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;        &lt;/SPAN&gt;[&lt;/FONT&gt;&lt;SPAN style="COLOR: #2b91af"&gt;XmlIgnore&lt;/SPAN&gt;&lt;FONT color=#000000&gt;]&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;        &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IDataErrorInfo&lt;/SPAN&gt;&lt;FONT color=#000000&gt;.&lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;&lt;FONT color=#000000&gt;[&lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&lt;FONT color=#000000&gt; columnName] { &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;&lt;FONT color=#000000&gt; { &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt;&lt;FONT color=#000000&gt;(GetPropertyError(columnName)); } }&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;        &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;virtual&lt;/SPAN&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&lt;FONT color=#000000&gt; GetPropertyError(&lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&lt;FONT color=#000000&gt; propertyName)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;        &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;            &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;SPAN style="COLOR: #a31515"&gt;""&lt;/SPAN&gt;&lt;FONT color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;        &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;        &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;virtual&lt;/SPAN&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&lt;FONT color=#000000&gt; GetErrors()&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;        &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;            &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;StringBuilder&lt;/SPAN&gt;&lt;FONT color=#000000&gt; sb = &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;SPAN style="COLOR: #2b91af"&gt;StringBuilder&lt;/SPAN&gt;&lt;FONT color=#000000&gt;();&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;            &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//todo: add code to loop through properties and return error&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;            &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//todo: add code to check contraints&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;            &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt;&lt;FONT color=#000000&gt; oclService = AsIObject().ServiceProvider.GetEcoService&amp;lt;&lt;/FONT&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IOclService&lt;/SPAN&gt;&lt;FONT color=#000000&gt;&amp;gt;();&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;            &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//todo: this is a first stab at getting constraint errors, it has not been tested&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;            &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;foreach&lt;/SPAN&gt;&lt;FONT color=#000000&gt; ( &lt;/FONT&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IConstraint&lt;/SPAN&gt;&lt;FONT color=#000000&gt; constraint &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt;&lt;FONT color=#000000&gt; AsIObject().UmlType.Constraints ) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;                &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IElement&lt;/SPAN&gt;&lt;FONT color=#000000&gt; oclResult = oclService.Evaluate(AsIObject(), constraint.Body.Body);&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;                &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;&lt;FONT color=#000000&gt; ( oclResult.GetValue&amp;lt;&lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;bool&lt;/SPAN&gt;&lt;FONT color=#000000&gt;&amp;gt;() ) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;                    &lt;/SPAN&gt;sb.Append(constraint.Description);&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;                    &lt;/SPAN&gt;sb.Append(&lt;/FONT&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Environment&lt;/SPAN&gt;&lt;FONT color=#000000&gt;.NewLine);&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;    &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;            &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;            &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;            &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt;&lt;FONT color=#000000&gt; sb.ToString();&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;        &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;        &lt;/SPAN&gt;#endregion&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; COLOR: blue; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt; &lt;/P&gt;&lt;P style="BACKGROUND: white"&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;Note, that an empty string from the GetPropertyError represents a non-error condition.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;The GetErrors method returns all errors that exist on the object.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;I have more work to do here, but the beauty is that I only need to do this once and everything will use it.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;I also plan to add a similar GetErrors method to my EcoSpace that will loop through all modified objects and call each objects GetErrors method to get all errors that exist from a user’s changes.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;If any errors exist, I will not allow the changes to be saved.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;On the form the user gets an error message that contains the same text that GetErrors returns.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;Also, each control that has a corresponding error gets an indicator showing where the error exists.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;By using this pattern you do not have to do any coding on your forms to get full error handling.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;The coding is done once in the validation controls that I mentioned above.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="BACKGROUND: white"&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;Here is how I validate that the FirstName and LastName are required in my Person object:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;        &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;override&lt;/SPAN&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&lt;FONT color=#000000&gt; GetPropertyError(&lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&lt;FONT color=#000000&gt; propertyName)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;        &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;            &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&lt;FONT color=#000000&gt; result = &lt;/FONT&gt;&lt;SPAN style="COLOR: #a31515"&gt;""&lt;/SPAN&gt;&lt;FONT color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;            &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;switch&lt;/SPAN&gt;&lt;FONT color=#000000&gt; ( propertyName ) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;                &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;case&lt;/SPAN&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;SPAN style="COLOR: #a31515"&gt;"FirstName"&lt;/SPAN&gt;&lt;FONT color=#000000&gt;: {&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;    &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;                    &lt;/SPAN&gt;&lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;&lt;FONT color=#000000&gt; ( &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&lt;FONT color=#000000&gt;.IsNullOrEmpty(FirstName) ) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;                            &lt;/SPAN&gt;result = GetRequiredPrompt(propertyName);&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;                        &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;                        &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;break&lt;/SPAN&gt;&lt;FONT color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;                    &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;                &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;case&lt;/SPAN&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;SPAN style="COLOR: #a31515"&gt;"LastName"&lt;/SPAN&gt;&lt;FONT color=#000000&gt;: {&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;           &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;             &lt;/SPAN&gt;&lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;&lt;FONT color=#000000&gt; ( &lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&lt;FONT color=#000000&gt;.IsNullOrEmpty(LastName) ) {&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;                            &lt;/SPAN&gt;result = GetRequiredPrompt(propertyName);&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;                        &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;                        &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;break&lt;/SPAN&gt;&lt;FONT color=#000000&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;                    &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;            &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;FONT color=#000000&gt;            &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt;&lt;FONT color=#000000&gt; result;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; FONT-SIZE: 10pt; mso-no-proof: yes"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;        &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none" class=MsoNormal&gt; &lt;/P&gt;&lt;P style="BACKGROUND: white"&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;This is rather simple, but I use this for very complex validation as well.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="BACKGROUND: white"&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;In your situation you could check for at least one detail (B) in your master (A) object’s GetPropertyError method.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;There is a lot of benefit to not throw exceptions when enforcing constraints.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;It raises havoc with data binding in both winforms and wpf.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;By allowing changes to happen and putting the object into an error state eliminates the deadlock situations.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="BACKGROUND: white"&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;Hope this is understandable.&lt;SPAN style="mso-spacerun: yes"&gt;  &lt;/SPAN&gt;It is hard to explain all this in a forum entry.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="BACKGROUND: white"&gt;&lt;SPAN style="FONT-FAMILY: Verdana; COLOR: #1f5080; FONT-SIZE: 10pt"&gt;Brian &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in -1.25in 0pt 0in" class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT color=#000000 size=3 face="Times New Roman"&gt; &lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;P style="MARGIN: 0in 0in 0pt; BACKGROUND: white; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT color=#000000 size=3 face="Times New Roman"&gt; &lt;/FONT&gt;&lt;/o:p&gt;</description><pubDate>Tue, 02 Mar 2010 00:25:55 GMT</pubDate><dc:creator>brian</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>Nevertheless I'm not happy with it. The first rule concerns deletion whereas the second rule is for existing items and I would prefer to separate these. </description><pubDate>Mon, 01 Mar 2010 11:02:20 GMT</pubDate><dc:creator>efim</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>After reading more closely, I see you are using the cascading delete functionality built into ECO.  In your situation you have two rules:  First, The cascading delete composition implies the details (b) must have a master (a).  Second, that the master must have at least one detail.  These two rules contradict one another during deletion.  It is similar to circular foreign key constraints in a database. &lt;P&gt;You must suppress one of the rules in order to accomplish a deletion.  So I would say your approach of suppressing the second rule is the best solution.&lt;/P&gt;&lt;P&gt;Brian</description><pubDate>Mon, 01 Mar 2010 00:26:40 GMT</pubDate><dc:creator>brian</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>Hi Brian,&lt;/P&gt;&lt;P&gt;I use AggregationKind, it is effectively the same as DeleteAction in ECO context. If you reread my posting you could see there 2 contradictory requirements: 1. Delete all subitems when item is about to be deleted (cascade deletion); 2. For each item it should exist at least 1 subitem. If ECO implemented cascade deletion in another order, I would have no problem: at first delete item, then subitems. But apparently the subitems are deleted at first, and that leads to collision with the second requirement.</description><pubDate>Sun, 28 Feb 2010 19:57:09 GMT</pubDate><dc:creator>efim</dc:creator></item><item><title>RE: Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>Why don't you want to use the DeleteAction property on an association end?  It has the options of &amp;lt;Default&amp;gt;, Allow, Prohibit, and Cascade.  I like the Default because then the Composition and Aggregation settings control the delete action.&lt;/P&gt;&lt;P&gt;I have been setting this property in my models, but I have not verified if it actually works.  I just assumed it did.  If it doesn't, please let us know what the problems are.&lt;/P&gt;&lt;P&gt;Brian</description><pubDate>Sat, 27 Feb 2010 07:20:21 GMT</pubDate><dc:creator>brian</dc:creator></item><item><title>Recommendation needed how to implement a special delete behaviour</title><link>http://www.capableobjects.com/apps/InstantForum414/Topic4909-4-1.aspx</link><description>Hi everybody,&lt;/P&gt;&lt;P&gt;I stuck with 2 requirements in business logic how to bring them together. Imagine 2 classes with 1..* association:&lt;/P&gt;&lt;P&gt; A 1 ----- * B&lt;/P&gt;&lt;P&gt;First requirement: cascade deletion - delete all Bs when A is to be deleted&lt;/P&gt;&lt;P&gt;The second one: for an instance of A at least one instance of B must exist (please don't come with constraints: I avoid them in general)&lt;/P&gt;&lt;P&gt;My problem: I have defined cascade deletion rule from A to B and PreDelete and SingleLinkModified for clas B like this:&lt;/P&gt;&lt;FONT size=2&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; PreDelete() {&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (a!= &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &amp;amp;&amp;amp; a.b.Count == 1) &lt;/FONT&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;throw&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;Exception&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;"At least one item must exist"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;);}&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;ISingleLinkCatcher&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.SingleLinkModified(&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;IAssociationEnd&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; ae, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;IEcoObject&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; oldValue, &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;IEcoObject&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; newValue) &lt;/FONT&gt;&lt;FONT size=2&gt;{&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (ae.LoopbackIndex == &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;Eco_LoopbackIndices&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;.A)&lt;/P&gt;&lt;P&gt;{  &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;A &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;oldA = (&lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;A&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;)oldValue;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (newValue == &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &amp;amp;&amp;amp; oldA.b.Count == 0)&lt;/P&gt;&lt;P&gt;{  this.a = oldA ;  &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;throw&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#2b91af size=2&gt;&lt;FONT color=#2b91af size=2&gt;Exception&lt;FONT color=#1f5080 size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;"At least one item must exist"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#1f5080 size=2&gt;)  &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;}  };  }&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT size=2&gt;When an instance of A is about to be deleted, it tries to delete all associated Bs, but the last can't be deleted because of the second rule. THe only solution I found is to use additional bool property "IsAboutToDelete" on class A that is set to true in A.PreDelete and checked in SingleLinkModified. Only if it is false the exception would be thrown.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT size=2&gt;Perhaps I miss a purer ECO solution here? Glad to hear of alternatives.&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT size=2&gt;/Efim&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;</description><pubDate>Fri, 26 Feb 2010 12:19:40 GMT</pubDate><dc:creator>efim</dc:creator></item></channel></rss>
