DSL Tools #11 - Preventing the User from Deleting Instances of a Domain Class

NOTE: The procedure described here is based on the domain model described in this previous post.

---

The next thing that I wanted to achieve in my DSL was to prevent the user from deleting manually the instances of certain domain classes.

On my example, since all the attributes are created automatically (by code) when each entity is added (also automatically), I don't want the user to be able to delete these attributes. That would create inconsistencies between this model and the model from where the entities were previously read.

Searching the Web for a solution, I came across 2 different articles about this:

Article #1

Article #2

The two articles define different approaches to the problem. The difference is basically the user experience you'll achieve depending when the solution you select.

Personally, I like to give clear feedback about why he can't do something very obvious. Also I tend to prefer the solution that requires less coding. So I went with the second.

1. Preventing the User from Deleting Embedding Relationships

If you look at the EntityHasNormalAttributes this is an embedding relationship that will be presented to the user has a compartment in the entity shape, containing all its normal attributes.

You prevent the user from deleting normal attributes if you prevent him from deleting this kind of relationship.

For that, you create a partial class for the EntityHasNormalAttributes and override the OnDeleting method. When you want to prevent the delete from happening, you need to throw an exception (InvalidOperationException is recommended). Like this:

   1: using System;
   2: using Microsoft.VisualStudio.Modeling;
   3:  
   4: namespace MyDSL
   5: {
   6:     /// <summary>
   7:     /// Provides custom behavior for the EntityHasNormalAttributes domain class.
   8:     /// </summary>
   9:     public partial class EntityHasNormalAttributes
  10:     {
  11:         #region Public Methods
  12:  
  13:         /// <summary>
  14:         /// Called when an instance of this domain class is being deleted.
  15:         /// </summary>
  16:         protected override void OnDeleting()
  17:         {
  18:             // Default behavior
  19:  
  20:             base.OnDeleting();
  21:  
  22:             // You can't delete normal attributes from entities
  23:  
  24:             if ((this.Entity != null) && (!this.Entity.IsDeleting))
  25:             {
  26:                 throw new InvalidOperationException(Properties.Resources.RES_Error_CannotDeleteAttribute);
  27:             }
  28:         }
  29:  
  30:         #endregion
  31:     }
  32: }

Notice that the exception is only thrown if Entity.IsDeleting is false. This means that you only want to prevent the relationship from being removed if you're not deleting the entity itself.

2. Preventing the User from Deleting Reference Relationships

My domain model also includes a reference relationship that I want to create at runtime (when the user "imports" the model) and prevent from being removed latter by him (manually).

Click to see full size image

In this case I want to prevent the connector from being removed. So the implementation is very similar: override IsDeleting in ModuleReferenceUsesEntities:

   1: using System;
   2:  
   3: namespace MyDSL
   4: {
   5:     /// <summary>
   6:     /// Provides custom behavior for the ModuleReferenceUsesEntities domain class.
   7:     /// </summary>
   8:     public partial class ModuleReferenceUsesEntities
   9:     {
  10:         #region Public Methods
  11:  
  12:         /// <summary>
  13:         /// Called when an instance of this domain class is being deleted.
  14:         /// </summary>
  15:         protected override void OnDeleting()
  16:         {
  17:             // Default behavior
  18:  
  19:             base.OnDeleting();
  20:  
  21:             // You cannot delete connections between module references and entities
  22:             // If we're deleting the module reference, then it's ok
  23:             // If we're deleting the entity, then it's ok
  24:  
  25:             if (this.ModuleReference == null || this.ModuleReference.IsDeleting)
  26:             {
  27:                 return;
  28:             }
  29:             if (this.Entity == null || this.Entity.IsDeleting)
  30:             {
  31:                 return;
  32:             }
  33:  
  34:             throw new InvalidOperationException(Properties.Resources.RES_Error_CannotDeleteModuleReferenceEntityConnection);
  35:         }
  36:  
  37:         #endregion
  38:     }
  39: }

Notice now that the exception is only throw when neither the module reference or the entity is being removed. That is the case when the user tries to delete the connector itself between these two domain classes.

---

NOTE: The procedure described here is based on the domain model described in this previous post.

Published 15 July 08 06:25 by hgr
Filed under: ,

Comments

# Hugo Ribeiro said on July 15, 2008 6:36 PM:

NOTE: The procedure described here is based on the domain model described in this previous post . ---

# Hugo Ribeiro said on July 15, 2008 6:43 PM:

Since I've been doing a number of posts on the DSL Tools, I thought it would be helpful to have a list

Anonymous comments are disabled