I'd like to write the following in script syntax rather than the old style tag syntax.
<cfcomponent persistent="true" table="AuditType" schema="Audit" >
<cfproperty name="AuditTypeID" column="AuditTypeID" ormtype="int" fieldtype="id" />
<cfproperty name="AuditTypeName" column="AuditTypeName" ormtype="string" />
<cfproperty name="AuditTypeSort" column="AuditTypeSort" ormtype="integer" />
</cfcomponent>
the cfscript syntax really is quite similar,
component persistent="true" table="AuditType" schema="Audit" {
property name="AuditTypeID" column="AuditTypeID" ormtype="int" fieldtype="id";
property name="AuditTypeName" column="AuditTypeName" ormtype="string";
property name="AuditTypeSort" column="AuditTypeSort" ormtype="integer";
}
Related
Mapping Two cfc objects via ORM, on execution a Dump shows the data for only one parent cfc object for table=products while the array of cfc table=department is coming back as (empty string) in output .
<cfcomponent persistent="true" table="products" >
<cfproperty name="productID" column="id" fieldtype="id" type="numeric" generator="increment">
<cfproperty name="name">
<cfproperty name="price">
<cfproperty name="description">
<cfproperty name="imageurl">
<cfproperty name="departmt" fieldtype="many-to-one" cfc="departmt" fkcolumn="dept_id" lazy="true">
<cfcomponent persistent="true" table="department">
<cfproperty name="id" column="dept_id" fieldtype="id" type="numeric" generator="increment">
<cfproperty name="name" column="dept_name">
<cfproperty name="location" >
</cfcomponent>
I have two objects, Person and Family. I use a join table called "join_person_family" to track this many-to-many relationship. The join table has another property called "IS_PRIMARY" that I want to get at and filter when instantiating the person objects with EntityLoadByExample(), but I don't know how to do this with CF ORM. I could do this easily through SQL, but I'm trying to use ORM as much as possible. There may also be another way to track this property, but I can't think of anything. Thanks in advance for any help.
Here is the Family.cfc:
<cfcomponent hint="I am a Family" output="false" persistent="true" extends="_Proxy">
<cfproperty name="FAMILY_ID" hint="FAMILY_ID" type="numeric" ormtype="int" length="11" fieldtype="id" generator="identity" required="true"/>
<cfproperty name="PERSON" hint="PERSON" fieldtype="many-to-many" cfc="person" linktable="join_family_person" FKColumn="FAMILY_ID" inversejoincolumn="PERSON_ID" lazy="true"/>
<cfproperty name="STATUS" type="string" ormtype="string" length="45"/>
<cfproperty name="COMMENT" hint="COMMENT" type="string" length="255"/>
<cffunction name="init" hint="constructor" access="public" returntype="family" output="false">
<cfscript>
return this;
</cfscript>
</cffunction>
</cfcomponent>
Here is the Person.cfc:
<cfcomponent hint="I am a Person" output="false" persistent="true" extends="_Proxy">
<cfproperty name="FAMILY" hint="FAMILY" fieldtype="many-to-many" cfc="family" linktable="join_family_person" FKColumn="PERSON_ID" inversejoincolumn="FAMILY_ID" lazy="true"/>
<cfproperty name="PERSON_ID" hint="PERSON_ID" type="numeric" ormtype="int" length="11" fieldtype="id" generator="identity" required="true"/>
<cfproperty name="USER" hint="USER" fieldtype="one-to-one" cfc="mend_user" FKColumn="USER_ID" lazy="true"/>
<cfproperty name="FIRST_NAME" hint="FIRST_NAME" type="string" length="45"/>
<cfproperty name="LAST_NAME" hint="LAST_NAME" type="string" length="45"/>
<cfproperty name="STATUS" hint="STATUS" type="numeric" ormtype="int"/>
<cffunction name="init" hint="constructor" access="public" returntype="person" output="false">
<cfscript>
return this;
</cfscript>
</cffunction>
Found this response, https://groups.google.com/forum/?hl=en&fromgroups=#!topic/cf-orm-dev/6Fox77MAcbs. After reading that I think that approach is actually superior anyway.
A intermediate entity with many-to-one relationships with the joining objects would allow me to use EntityLoadByExample() to get the relevant person objects filtered by "IS_PRIMARY". Then I could filter the person objects if need be.
I work primarily in ColdFusion, a non-compiled language, but this is a general question for all languages.
I'm creating objects with getters/setters as well as CRUD methods. Here's a sample:
<cffunction name="getPeriodStartDate" output="false" returntype="Numeric">
<cfreturn VARIABLES.PeriodStartDate />
</cffunction>
<cffunction name="setPeriodStartDate" output="false" returntype="Void">
<cfargument name="PeriodStartDate" type="Numeric" required="true" />
<cfset VARIABLES.PeriodStartDate = ARGUMENTS.PeriodStartDate />
</cffunction>
<cffunction name="getDollarAmount" output="false" returntype="Numeric">
<cfreturn VARIABLES.DollarAmount />
</cffunction>
<cffunction name="setDollarAmount" output="false" returntype="Void">
<cfargument name="DollarAmount" type="Numeric" required="true" />
<cfset VARIABLES.DollarAmount = ARGUMENTS.DollarAmount />
</cffunction>
<cffunction name="read" output="false" returntype="Query">
<!---
READ QUERY
--->
<cfreturn _qData />
</cffunction>
<cffunction name="create" output="false" returntype="Void">
<!---
INSERT QUERY
--->
</cffunction>
<cffunction name="update" output="false" returntype="Void">
<!---
UPDATE QUERY
--->
</cffunction>
<cffunction name="delete" output="false" returntype="Void">
<!---
DELETE QUERY
--->
</cffunction>
Obviously the get methods and the read() methods will return a value.
But, is there any benefit to have the other methods return a value - perhaps a Boolean?
I've worked in Flex/ActionScript and remember that in most cases, I needed to return some value from a method and set a variable to that result in order to prevent the next line of code from processing:
function myFunc() {
x = getSomething();
y = getSomethingElse(x);
}
If you return this on your setters, you can chain the setters. I think CF10 accessors return thisto enable chaining by default.
I read that returning void would be more efficient a while back, but I'm not sure if it is true anymore. I doubt the difference would be noticeable.
I have Odata service which exposes "StartAction" service operation. This operation returns ActionResponse entity
<EntityType Name="ActionResponse">
<Key>
<PropertyRef Name="FolderId" />
</Key>
<Property Name="FolderId" Type="Edm.String" Nullable="false" />
<Property Name="ClientData" Type="Edm.String" Nullable="true" />
<Property Name="ProcessCaption" Type="Edm.String" Nullable="true" />
<Property Name="ProcessName" Type="Edm.String" Nullable="true" />
<Property Name="ProjectName" Type="Edm.String" Nullable="true" />
<Property Name="ProjectVersion" Type="Edm.Int32" Nullable="false" />
<Property Name="ServerData" Type="Edm.String" Nullable="true" />
<Property Name="StageName" Type="Edm.String" Nullable="true" />
<Property Name="UserName" Type="Edm.String" Nullable="true" />
<NavigationProperty Name="Action" Relationship="Metastorm.EngineData.ActionResponse_Action_Action_ActionResponse" FromRole="ActionResponse_Action" ToRole="Action_ActionResponse" />
</EntityType>
<Association Name="ActionResponse_Action_Action_ActionResponse">
<End Role="ActionResponse_Action" Type="Metastorm.EngineData.ActionResponse" Multiplicity="0..1" />
<End Role="Action_ActionResponse" Type="Metastorm.EngineData.Action" Multiplicity="0..1" />
</Association>
when i try to $expand Action navigation property, i get the following error:
Query options $expand, $filter, $orderby, $inlinecount, $skip and $top cannot be applied to the requested resource
I can work it around if i will return IQueryable with only one item, but is looks ugly. Does anyone know any other way how to make $expand work for Service Operations which return a single entity?
Thanks in advance
P.S. The service have custom implementation
The service operation must return IQueryable in order for any of the other query options to work (this is necessary, since WCF DS needs the IQueryable to construct the expression for the additional query options).
It is perfectly fine to return an IQueryable with a single result in it. Add the [SingleResult] attribute on the service operation method to let WCF DS know that the IQueryable is only gonna return a single value (and so that the query options behave accordingly).
I have two almost identical Beans.
Bean "Item" contains a unique identifier (primary key), a name and an array that contains structs with data for different Users that are related to the "Item".
Bean "User" contains a unique identifier (primary key), a firstname, a lastname and an array that contains structs with data of different Items that are related to the "User".
Both components contain two methods that write new data to the structs in the array or delete array elements and the setters and getters for the arguments.
The components deviate from each other only through theire argument names, the number of arguments each init method takes and the number of getters and setters.
So i want to create an "Abstract" Bean from which "Item" and "User" inherit. I can do so by using extends in the Beans to get the abstract methods, but how do i override the argument names and variable names. I.e. the argument name ArrayOfData in the AbstractBean does not really tell someone anything. I would like to have ItemHasMaterialsArray and UserHasItemsArray as names in the Item and User beans.
AbstractBean
<cfcomponent name="AbstractBean" output="false">
<cffunction name="init" access="public" hint="constructor" returntype="AbtractBean">
<cfargument name="Identifier" required="false" type="Numeric" default="0">
<cfargument name="Name" required="false" type="String" default="">
<cfargument name="ArrayOfData" required="false" type="Array" default="#arrayNew(1)#">
<cfset variables.instance = structNew() />
<cfset setIdentifier(arguments.identifier) />
<cfset setName(arguments.name) />
<cfset setArrayOfData(arguments.ArrayOfData) />
<cfreturn this />
</cffunction>
<cffunction name="updateArrayOfData" access="public" output="true" returntype="boolean">
<cfargument name="blank" type="Struct" required="true">
<cfset var i = 0 />
<cfset var form = arguments.blank />
<cfset var ArrayOfData = arrayNew(1) />
<cfset ArrayOfData = this.getArrayOfData() />
<cfloop index="i" from="#arrayLen(ArrayOfData)#" to="1" step="-1">
<cfif ArrayOfData[i].Amount neq structFind(form,ArrayOfData[i].Id) and LsIsNumeric(structFind(form,ArrayOfData[i].Id))>
<cfset ArrayOfData[i].Amount = structFind(form,ArrayOfData[i].Id) />
<cfelse>
<cfset arrayDeleteAt(ArrayOfData,i) />
</cfif>
</cfloop>
<cfset setArrayOfData(ArrayOfData) />
<cfreturn true />
</cffunction>
<cffunction name="deleteArrayOfDataElement" access="public" output="false" returntype="boolean">
<cfargument name="blank" type="Struct" required="true">
<cfset var i = 0 />
<cfset var form = arguments.blank />
<cfset var ArrayOfData = arrayNew(1) />
<cfset ArrayOfData = this.getArrayOfData() />
<cfloop index="i" from="#arrayLen(ArrayOfData)#" to="1" step="-1">
<cfif not listFind(form.del,ArrayOfData[i].UserId,',')>
<cfset arrayDeleteAt(ArrayOfData,i) />
</cfif>
</cfloop>
<cfset setArrayOfData(ArrayOfData) />
<cfreturn true />
</cffunction>
<cffunction name="setIdentifier" hint="setter" access="private" output="false" returntype="Void">
<cfargument name="identifier" required="true" type="Numeric" hint="Primary Key, really" />
<cfset variables.instance.Identifier = arguments.Identifier />
</cffunction>
<cffunction name="getIdentifier" hint="getter" access="public" output="false" returntype="Numeric">
<cfreturn variables.instance.identifier />
</cffunction>
<cffunction name="setName" access="private" output="false" returntype="Void">
<cfargument name="name" required="true" type="String" />
<cfset variables.instance.Name = arguments.Name />
</cffunction>
<cffunction name="getName" access="public" output="false" returntype="String">
<cfreturn variables.instance.Name />
</cffunction>
<cffunction name="setArrayOfData" access="private" output="false" returntype="Void">
<cfargument name="ArrayOfData" required="true" type="Array" />
<cfset variables.instance.ArrayOfData = arguments.ArrayOfData />
</cffunction>
<cffunction name="getArrayOfData" access="public" output="false" returntype="Array">
<cfreturn variables.instance.ArrayOfData />
</cffunction>
</cfcomponent>
In my User bean i would like the init method to also take firstname as an argument and override the variable names in my methods. With telling names my other code, i.e. calling the getters, would be much cleaner. User.getUserHasMaterials() reads much better than User.getArrayOfData(), imo. is this even possible? If not than i guess i will have to sacrifice variables readability to avoid duplication.
I think if you're trying to avoid duplication, it might make more sense to use composition rather than inheritance.
It looks like ArrayOfData could be be its own CFC, with methods like update(), delete(), and toArray(). Then you could pass an instance of ArrayOfData to either your User or Item object.
Your User CFC might look something like this:
<cfcomponent name="User">
<cffunction name="init" access="public" hint="constructor" returntype="User">
...
<cfargument
name="materials"
required="false"
type="ArrayOfData"
default="#arrayNew(1)#"
>
...
<cfset variables.materials = createObject("component", "ArrayOfData")>
<cfset setMaterials(arguments.materials)/>
<cfreturn this />
</cffunction>
<cffunction name="setMaterials">
<cfargument name="value" type="Array">
<cfset variables.materials.update(arguments.value)>
</cffunction>
<cffunction name="getMaterials">
<cfreturn variables.materials.toArray()>
</cffunction>
<cffunction name="deleteMaterials">
<cfargument name="blank">
<cfset variables.materials.delete(arguments.blank)>
</cffunction>