From 0e392e6bb3bfe79d0b423322cfc751cdad99bf6c Mon Sep 17 00:00:00 2001 From: sb <sb> Date: Thu, 8 May 2008 17:26:44 +0000 Subject: [PATCH] bug 1833 : Added distinctness checks to controller generator; also transactions. --- transforms01/adl2controllerclasses.xslt | 458 +++++++++++++++--------- 1 file changed, 291 insertions(+), 167 deletions(-) diff --git a/transforms01/adl2controllerclasses.xslt b/transforms01/adl2controllerclasses.xslt index 2e9de19..beac2ae 100755 --- a/transforms01/adl2controllerclasses.xslt +++ b/transforms01/adl2controllerclasses.xslt @@ -9,8 +9,8 @@ Transform ADL into (partial) controller classes $Author: sb $ - $Revision: 1.22 $ - $Date: 2008-04-18 09:27:29 $ + $Revision: 1.23 $ + $Date: 2008-05-08 17:26:44 $ --> <!-- WARNING WARNING WARNING: Do NOT reformat this file! @@ -71,7 +71,7 @@ // // Controller for auto-generated forms for editing <xsl:value-of select="@name"/>s // Automatically generated from application description using -// adl2controllerclasses.xslt version <xsl:value-of select="substring( '$Revision: 1.22 $', 10)"/> +// adl2controllerclasses.xslt version <xsl:value-of select="substring( '$Revision: 1.23 $', 10)"/> // // This file is automatically generated; DO NOT EDIT IT. // @@ -128,7 +128,7 @@ namespace <xsl:value-of select="$controllerns"/> { // // Controller for auto-generated forms for editing <xsl:value-of select="@name"/>s // Automatically generated from application description using -// adl2controllerclasses.xslt version <xsl:value-of select="substring( '$Revision: 1.22 $', 10)"/> +// adl2controllerclasses.xslt version <xsl:value-of select="substring( '$Revision: 1.23 $', 10)"/> // // This file is automatically generated; DO NOT EDIT IT. // @@ -186,18 +186,27 @@ namespace <xsl:value-of select="$controllerns"/> { // update permissions, seeing that we use an update operation to set the // field values and save the entity. Boolean isnewborn = false; + + <xsl:call-template name="fetch-instance"> + <xsl:with-param name="entity" select="."/> + <xsl:with-param name="initialise-locals" select="'true'"/> + </xsl:call-template> + + try { + <xsl:if test="adl:property[@distinct='system' or @distinct='all']"> + /* declare a list of <xsl:value-of select="@name"/> to use in + * distinctness checks */ + IList<<xsl:value-of select="@name"/>> matches = null; + </xsl:if> <xsl:apply-templates select="descendant::adl:property"/> - <xsl:call-template name="fetch-instance"> - <xsl:with-param name="entity" select="."/> - </xsl:call-template> - - if ( record == null) { - /* it seems to be new, create persistent object */ - AssertUserCanCreate(); - try { - record = new <xsl:value-of select="concat($entityns, '.', @name)"/>(<xsl:for-each select="adl:key/adl:property"> + if ( record == null) { + /* it seems to be new, create persistent object */ + AssertUserCanCreate(); + + try { + record = new <xsl:value-of select="concat($entityns, '.', @name)"/>(<xsl:for-each select="adl:key/adl:property"> <xsl:variable name="basetype"> <xsl:call-template name="base-type"> <xsl:with-param name="property" select="."/> @@ -227,69 +236,72 @@ namespace <xsl:value-of select="$controllerns"/> { <xsl:otherwise>, </xsl:otherwise> </xsl:choose> </xsl:for-each>); + } + catch ( FormatException) { + /* failed to parse a number - not wholly unexpected, since it's most likely + that an empty string was passed in */ + record = new <xsl:value-of select="concat($entityns, '.', @name)"/>(); + } + catch ( NullReferenceException) { + /* again, probably more normal than otherwise */ + record = new <xsl:value-of select="concat($entityns, '.', @name)"/>(); + } + messages.Add( "New <xsl:value-of select="@name"/> record created"); + isnewborn = true; } - catch ( FormatException) { - /* failed to parse a number - not wholly unexpected, since it's most likely - that an empty string was passed in */ - record = new <xsl:value-of select="concat($entityns, '.', @name)"/>(); - } - catch ( NullReferenceException) { - /* again, probably more normal than otherwise */ - record = new <xsl:value-of select="concat($entityns, '.', @name)"/>(); - } - messages.Add( "New <xsl:value-of select="@name"/> record created"); - isnewborn = true; - } - if ( record != null) { - if ( ! isnewborn) { - // isnewborn cannot be true unless we've already checked user can create - // so no need to do it again here - AssertUserCanUpdate(); - } + if ( record != null) { + /* a transaction to ensure our database operations are atomic */ + ITransaction tx = null; + + if ( ! isnewborn) { + // isnewborn cannot be true unless we've already checked user can create + // so no need to do it again here + AssertUserCanUpdate(); + } - try { - /* actually update the record */ - BindObjectInstance( record, ParamStore.Form, "instance"); + try { + /* actually update the record */ + BindObjectInstance( record, ParamStore.Form, "instance"); <xsl:if test="descendant::adl:property[@type='message']"> - /* there is at least one slot whose value is an internationalised message; - * if these have yet to be initialised they must be handled specially */ - Locale locale = GetBestLocaleForUser(); + /* there is at least one slot whose value is an internationalised message; + * if these have yet to be initialised they must be handled specially */ + Locale locale = GetBestLocaleForUser(); <xsl:for-each select="descendant::adl:property[@type='message']"> - if ( ! String.IsNullOrEmpty( Form["<xsl:value-of select="concat( 'i18n.instance.', @name)"/>"])){ - /* there's an uninitialised message for this slot */ - Message mess = record.<xsl:value-of select="@name"/>; - if ( mess == null){ - mess = new Message(); - } - hibernator.Save( mess); + if ( ! String.IsNullOrEmpty( Form["<xsl:value-of select="concat( 'i18n.instance.', @name)"/>"])){ + /* there's an uninitialised message for this slot */ + Message mess = record.<xsl:value-of select="@name"/>; + if ( mess == null){ + mess = new Message(); + } + hibernator.Save( mess); - Translation trans = mess.GetTranslationObject( locale, hibernator); - if ( trans == null) { - trans = new Translation( mess, locale); + Translation trans = mess.GetTranslationObject( locale, hibernator); + if ( trans == null) { + trans = new Translation( mess, locale); + } + trans.MessageText = Form["<xsl:value-of select="concat( 'i18n.instance.', @name)"/>"]; + record.<xsl:value-of select="@name"/> = mess; + hibernator.Save( trans); } - trans.MessageText = Form["<xsl:value-of select="concat( 'i18n.instance.', @name)"/>"]; - record.<xsl:value-of select="@name"/> = mess; - hibernator.Save( trans); - } </xsl:for-each> </xsl:if> <xsl:for-each select="descendant::adl:property[@type='entity']"> - /* for properties of type 'entity', it should not be necessary to do anything - * special - BindObjectInstance /should/ do it all. Unfortunately it sometimes - * doesn't, and I haven't yet characterised why not. */ + /* for properties of type 'entity', it should not be necessary to do anything + * special - BindObjectInstance /should/ do it all. Unfortunately it sometimes + * doesn't, and I haven't yet characterised why not. */ <xsl:variable name="entityname" select="@entity"/> <xsl:choose> <xsl:when test="//adl:entity[@name=$entityname]"> - if ( ! String.IsNullOrEmpty( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])) - { - record.<xsl:value-of select="@name"/> = <xsl:call-template name="fetch-property-instance"> + if ( ! String.IsNullOrEmpty( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])) + { + record.<xsl:value-of select="@name"/> = <xsl:call-template name="fetch-property-instance"> <xsl:with-param name="property" select="."/> <xsl:with-param name="valuename" select="concat( 'instance.', @name)"/> </xsl:call-template>; - } + } </xsl:when> <xsl:otherwise> <xsl:message terminate="yes"> @@ -301,120 +313,132 @@ namespace <xsl:value-of select="$controllerns"/> { </xsl:for-each> <xsl:for-each select="property[@type='link']"> - /* to update a link table which has no other data than the near and far keys, it is - * sufficient to smash the existing values and create new ones. It's also a lot easier! */ + /* to update a link table which has no other data than the near and far keys, it is + * sufficient to smash the existing values and create new ones. It's also a lot easier! */ - string[] <xsl:value-of select="concat(@name, 'Values')"/> = Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>"); + string[] <xsl:value-of select="concat(@name, 'Values')"/> = Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>"); - if ( <xsl:value-of select="concat(@name, 'Values')"/> != null) - { - /* update the linking table for my <xsl:value-of select="@name"/>; first smash the old values */ - if ( <xsl:value-of select="concat( 'record.', @name)"/> != null) + if ( <xsl:value-of select="concat(@name, 'Values')"/> != null) { - <xsl:value-of select="concat( 'record.', @name)"/>.Clear(); - } - else - { - <xsl:value-of select="concat( 'record.', @name)"/> = new HashedSet<<xsl:value-of select="@entity"/>>(); - } + /* update the linking table for my <xsl:value-of select="@name"/>; first smash the old values */ + if ( <xsl:value-of select="concat( 'record.', @name)"/> != null) + { + <xsl:value-of select="concat( 'record.', @name)"/>.Clear(); + } + else + { + <xsl:value-of select="concat( 'record.', @name)"/> = new HashedSet<<xsl:value-of select="@entity"/>>(); + } - /* then reinstate the values from the indexes passed */ - foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>) - { + /* then reinstate the values from the indexes passed */ + foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>) + { <xsl:value-of select="concat( 'record.', @name)"/>.Add( hibernator.CreateCriteria(typeof(<xsl:value-of select="@entity"/>)) .Add(Expression.Eq("<xsl:value-of select="@entity"/>Id", index)) .UniqueResult<<xsl:value-of select="$entityns"/>.<xsl:value-of select="@entity"/>>()); + } } - } </xsl:for-each> <xsl:for-each select="descendant::adl:property[@type='list']"> - /* with a list we cannot just smash the old values! Instead we need to check - * each one and exclude it if no longer required */ - if ( Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>") != null) - { - string[] <xsl:value-of select="concat(@name, 'Values')"/> = Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>"); - - /* updating <xsl:value-of select="@name"/> child records; first remove any not on the submitted list */ - foreach ( <xsl:value-of select="@entity"/> item in record.<xsl:value-of select="@name"/>) + /* with a list we cannot just smash the old values! Instead we need to check + * each one and exclude it if no longer required */ + if ( Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>") != null) { - String itemId = item.KeyString; - bool found = false; + string[] <xsl:value-of select="concat(@name, 'Values')"/> = Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>"); + /* updating <xsl:value-of select="@name"/> child records; first remove any not on the submitted list */ + foreach ( <xsl:value-of select="@entity"/> item in record.<xsl:value-of select="@name"/>) + { + String itemId = item.KeyString; + bool found = false; + + foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>) + { + <!-- TODO: this could definitely be made more efficient --> + if ( index.Equals( itemId)) + { + found = true; + break; + } + } + + if ( ! found) + { + record.<xsl:value-of select="@name"/>.Remove( item); + } + } /* foreach ( string index... */ + + /* then add any on the included list which are not already members */ foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>) { - <!-- TODO: this could definitely be made more efficient --> - if ( index.Equals( itemId)) - { - found = true; - } - } - - if ( ! found) - { - record.<xsl:value-of select="@name"/>.Remove( item); - } - } - - /* then add any on the included list which are not already members */ - foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>) - { <xsl:variable name="entityname" select="@entity"/> - <xsl:value-of select="@entity"/> item = - hibernator.CreateCriteria(typeof(<xsl:value-of select="@entity"/>)) - .Add(Expression.Eq("<xsl:value-of select="@entity"/>Id", index)) - .UniqueResult<<xsl:value-of select="$entityns"/>.<xsl:value-of select="@entity"/>>(); + <xsl:value-of select="@entity"/> item = + hibernator.CreateCriteria(typeof(<xsl:value-of select="@entity"/>)) + .Add(Expression.Eq("<xsl:value-of select="@entity"/>Id", index)) + .UniqueResult<<xsl:value-of select="$entityns"/>.<xsl:value-of select="@entity"/>>(); - if ( ! record.<xsl:value-of select="@name"/>.Contains( item)) - { - record.<xsl:value-of select="@name"/>.Add( item); - } - } - } + if ( ! record.<xsl:value-of select="@name"/>.Contains( item)) + { + record.<xsl:value-of select="@name"/>.Add( item); + } + } /* foreach ( string index... */ + } /* if ( Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>") != null) */ </xsl:for-each> - /* write the record to the database, in order to guarantee we have a valid key */ - hibernator.Save(record); - hibernator.Flush(); + /* write the record to the database, in order to guarantee we have a valid key */ + hibernator.Save(record); + hibernator.Flush(); + tx.Commit(); - messages.Add( "Record saved successfully"); - } - catch ( DataSuitabilityException dse) - { - AddError( dse.Message); - } - catch ( ApplicationException axe) - { - AddError( axe.Message); + messages.Add( "Record saved successfully"); + } /* try actually commit */ + catch ( Exception any) { + tx.Rollback(); + messages.Add( "Record not saved"); + throw any; + } + } /* if ( record != null) */ + else { + throw new ApplicationException( String.Format( "No record of type <xsl:value-of select="@name"/> with the key values supplied was found")); } + } /* try */ + catch ( DataSuitabilityException dse) + { + AddError( dse); + } + catch ( ApplicationException axe) + { + AddError( axe.Message); + } - PropertyBag["messages"] = messages; - PropertyBag["instance"] = record; + PropertyBag["messages"] = messages; + PropertyBag["instance"] = record; <xsl:if test="$authentication-layer = 'Database'"> - PropertyBag["username"] = Session[ NHibernateHelper.USERTOKEN]; + PropertyBag["username"] = Session[ NHibernateHelper.USERTOKEN]; </xsl:if> - if ( ! AssertNoErrors()) - { - /* the session may be polluted; create a new session */ - NHibernateHelper.CloseSession(); - hibernator = NHibernateHelper.GetCurrentSession(<xsl:if test="$authentication-layer = 'Database'"> - Session[ NHibernateHelper.USERTOKEN], - Session[NHibernateHelper.PASSTOKEN] - </xsl:if>); - } - - <xsl:call-template name="formmenus"> - <xsl:with-param name="form" select="adl:form[position()=1]"/> - </xsl:call-template> - RenderViewWithFailover("<xsl:value-of select="concat( adl:form[position()=1]/@name, '.vm')"/>", - "<xsl:value-of select="concat( adl:form[position()=1]/@name, '.auto.vm')"/>"); - } - else + if ( HasNoErrors()) { - throw new DataRequiredException( "Record not found"); - } + /* the session may be polluted; create a new session */ + NHibernateHelper.CloseSession(); + hibernator = NHibernateHelper.GetCurrentSession(<xsl:if test="$authentication-layer = 'Database'"> + Session[ NHibernateHelper.USERTOKEN], + Session[NHibernateHelper.PASSTOKEN] + </xsl:if>); + + <xsl:call-template name="fetch-instance"> + <xsl:with-param name="entity" select="."/> + <xsl:with-param name="initialise-locals" select="'false'"/> + </xsl:call-template> + + } + <xsl:call-template name="formmenus"> + <xsl:with-param name="form" select="adl:form[position()=1]"/> + </xsl:call-template> + RenderViewWithFailover("<xsl:value-of select="concat( adl:form[position()=1]/@name, '.vm')"/>", + "<xsl:value-of select="concat( adl:form[position()=1]/@name, '.auto.vm')"/>"); } </xsl:if> @@ -436,7 +460,8 @@ namespace <xsl:value-of select="$controllerns"/> { if ( "true".Equals( reallydelete)) { <xsl:call-template name="fetch-instance"> - <xsl:with-param name="entity" select="."/> + <xsl:with-param name="entity" select="."/> + <xsl:with-param name="initialise-locals" select="'true'"/> </xsl:call-template> if ( record != null) @@ -486,7 +511,7 @@ namespace <xsl:value-of select="$controllerns"/> { NHibernateHelper.GetCurrentSession( <xsl:if test="$authentication-layer = 'Database'">Session[ NHibernateHelper.USERTOKEN], Session[NHibernateHelper.PASSTOKEN]</xsl:if>); IList<<xsl:value-of select="concat( $entityns, '.', @name)"/>> instances = - hibernator.CreateCriteria(typeof(<xsl:value-of select="concat($entityns, '.', @name)"/>))<xsl:for-each select="property[@distinct='user']"> + hibernator.CreateCriteria(typeof(<xsl:value-of select="concat($entityns, '.', @name)"/>))<xsl:for-each select="adl:property[@distinct='user']"> <xsl:value-of select="concat( '.AddOrder( new Order( "', @name, '", true))')"/> </xsl:for-each>.List<<xsl:value-of select="concat($entityns, '.', @name)"/>>(); @@ -515,16 +540,41 @@ namespace <xsl:value-of select="$controllerns"/> { </xsl:choose>); } + <xsl:choose> + <xsl:when test="adl:property[@distinct='system']"> + <xsl:call-template name="check-property-value-distinct"> + <xsl:with-param name="property" select="."/> + </xsl:call-template> + </xsl:when> + <xsl:when test="adl:property[@distinct='all']"> + <xsl:call-template name="check-property-value-distinct"> + <xsl:with-param name="property" select="."/> + </xsl:call-template> + </xsl:when> + </xsl:choose> </xsl:template> - <!-- suppress properties otherwise --> - <xsl:template match="adl:property"/> - - <xsl:template match="adl:ifmissing"> - "<xsl:value-of select="normalize-space(.)"/>" - </xsl:template> + <xsl:template match="adl:property[@distinct='system']"> + <xsl:call-template name="check-property-value-distinct"> + <xsl:with-param name="property" select="."/> + </xsl:call-template> + </xsl:template> - <xsl:template match="adl:form"> + <xsl:template match="adl:property[@distinct='all']"> + <xsl:call-template name="check-property-value-distinct"> + <xsl:with-param name="property" select="."/> + </xsl:call-template> + </xsl:template> + + + <!-- suppress properties otherwise --> + <xsl:template match="adl:property"/> + + <xsl:template match="adl:ifmissing"> + "<xsl:value-of select="normalize-space(.)"/>" + </xsl:template> + + <xsl:template match="adl:form"> <!-- xsl:variable name="key"> <xsl:call-template name="primary-key-name"> <xsl:with-param name="entity" select="ancestor::adl:entity"/> @@ -539,16 +589,14 @@ namespace <xsl:value-of select="$controllerns"/> { /// Handle the submission of the form named <xsl:value-of select="@name"/> /// </summary> [AccessibleThrough(Verb.Post)] - public void <xsl:value-of select="concat( @name, 'SubmitHandler')"/>( ) - { - string command = Form[ "command"]; + public void <xsl:value-of select="concat( @name, 'SubmitHandler')"/>( ) { + string command = Form[ "command"]; - if ( command == null) - { - throw new Exception( "No command?"); - } - else - <xsl:for-each select=".//verb"> + if ( command == null) { + throw new Exception( "No command?"); + } + else + <xsl:for-each select=".//verb"> if ( command.Equals( "<xsl:value-of select="@verb"/>")) { /* NOTE: You must write an implementation of this verb in a @@ -565,6 +613,7 @@ namespace <xsl:value-of select="$controllerns"/> { <xsl:call-template name="fetch-instance"> <xsl:with-param name="entity" select="ancestor::adl:entity"/> + <xsl:with-param name="initialise-locals" select="'true'"/> </xsl:call-template> <xsl:if test="$authentication-layer = 'Database'"> @@ -716,7 +765,79 @@ namespace <xsl:value-of select="$controllerns"/> { /* <xsl:apply-templates/> */ </xsl:template> - <!-- produce all menus for a given form: harder, but more efficient --> + <!-- for properties with @distinct='all' or @distinct='system', + check that values are indeed distinct --> + <xsl:template name="check-property-value-distinct"> + <xsl:param name="property"/> + + <xsl:variable name="basetype"> + <xsl:call-template name="base-type"> + <xsl:with-param name="property" select="."/> + </xsl:call-template> + </xsl:variable> + + <xsl:choose> + <xsl:when test="$property/ancestor::adl:key and not( $property/ancestor::adl:entity/adl:key[position()=2])"> + <!-- if I'm the property of a key field and it is the only key field of my entity then + it is pointless trying to establish my distinctness --> + </xsl:when> + <xsl:when test="$property/@distinct = 'system' or $property/@distinct='all'"> + /* <xsl:value-of select="$property/@name"/> should be distinct: check that it is */ + matches = + hibernator.CreateCriteria(typeof(<xsl:value-of select="$property/ancestor::adl:entity/@name"/>)) + <xsl:choose> + <xsl:when test="$basetype='string'"> + .Add(Expression.Eq("<xsl:value-of select="$property/@name"/>", Form["<xsl:value-of select="concat('instance.', $property/@name)"/>"])) + </xsl:when> + <xsl:when test="$basetype='integer'"> + .Add(Expression.Eq("<xsl:value-of select="$property/@name"/>", Int32.Parse( Form["<xsl:value-of select="concat('instance.', $property/@name)"/>"]))) + </xsl:when> + <xsl:when test="$basetype='entity'"> + .Add(Expression.Eq("<xsl:value-of select="$property/@name"/>", + <xsl:call-template name="fetch-property-instance"> + <xsl:with-param name="property" select="."/> + <xsl:with-param name="valuename" select="adl:property[position()=1]/@name"/> + </xsl:call-template>)) + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + ADL: ERROR: don't yet know how to do distinctness checks for properties + with base type <xsl:value-of select="$basetype"/> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + <xsl:for-each select="$property/ancestor::adl:entity/adl:key"> + .Add(Expression.Not(Expression.Eq("<xsl:value-of select="adl:property[position()=1]/@name"/>",<xsl:choose> + <xsl:when test="@type='entity'"> + <xsl:call-template name="fetch-property-instance"> + <!-- recurse --> + <xsl:with-param name="property" select="."/> + <xsl:with-param name="valuename" select="adl:property[position()=1]/@name"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="@type='integer'"> + Int32.Parse( Form["<xsl:value-of select="adl:property[position()=1]/@name"/>"]) + </xsl:when> + <xsl:otherwise> + Form["<xsl:value-of select="adl:property[position()=1]/@name"/>"] + </xsl:otherwise> + </xsl:choose>))) + </xsl:for-each> + .List<<xsl:value-of select="$property/ancestor::adl:entity/@name"/>>(); + + if ( matches.Count > 0) + { + throw new + DataNotDistinctException( + String.Format("There is already a {0} with the {1} '{2}'", + "<xsl:value-of select="$property/ancestor::adl:entity/@name"/>", "<xsl:value-of select="$property/@name"/>", Form["<xsl:value-of select="concat('instance.', $property/@name)"/>"])); + } + </xsl:when> + </xsl:choose> + </xsl:template> + + + <!-- produce all menus for a given form: harder, but more efficient --> <xsl:template name="formmenus"> <xsl:param name="form"/> <xsl:choose> @@ -876,11 +997,15 @@ namespace <xsl:value-of select="$controllerns"/> { declared) called 'record' --> <xsl:template name="fetch-instance"> <xsl:param name="entity"/> - <xsl:value-of select="concat($entityns, '.', $entity/@name)"/> record = null; - + <xsl:param name="initialise-locals" select="'false'"/> /* check whether values for all key slots have been passed in; if so, we're probably dealing with an * existing record */ + <xsl:if test="$initialise-locals = 'true'"> + /* the instance (record) of type <xsl:value-of select="$entity/@name"/> we're dealing with */ + <xsl:value-of select="concat($entityns, '.', $entity/@name)"/> record = null; + /* whether we have valid values for all the key fields */ bool allkeys = true; + </xsl:if> <xsl:for-each select="$entity/adl:key/adl:property"> if ( String.IsNullOrEmpty( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])) { allkeys = false; @@ -893,7 +1018,6 @@ namespace <xsl:value-of select="$controllerns"/> { if ( allkeys){ /* it's (probably) existing, retrieve it */ - record = hibernator.CreateCriteria(typeof(<xsl:value-of select="concat( $entityns, '.', $entity/@name)"/>)) <xsl:for-each select="$entity/adl:key/adl:property"> <xsl:variable name="basetype">