I am not able to sort by CreationTimeUTC. I know it can be done using a RAW CFQL query, but is there a way using normal CFQL. Steps I tried are below:
Made CreationTimeUtc show in the entity as a property as shown below (sorry for putting it in a code snippet, stackoverflow is sometimes quirky with XML and this was the only way to get it to show)
<cf:property name="CreationTimeUtc" set="false" persistent="false" readOnLoad="true" typeName="datetime" dbType="DateTime" dataMember="false" persistenceName="_trackCreationTime" />
Created the CFQL query as shown below (sorry for using blockquote, stackoverflow is quirky again and it wouldn't format correctly in a codeblock):
LOADONE(Amikids.TimeTracking.PunchCard punchCard) WHERE IsVoid = FALSE
ORDER BY CreationTimeUtc DESC
Upon building the Model I get the following error:
Error 52 CF0291: An attempt to create a persistence order by column
snippet 'CreationTimeUtc' has been detected in procedure
'CompanyCodeAdjustment_LoadActiveByPunchCard'. Make sure order by
column identifiers declared in the body are valid in the context. If
you really want to create a snippet, you should change the project,
method or view 'checkLevel' attribute, currently set to 'Default'.
Below is the full XML for the entity.
<cf:entity name="CompanyCodeAdjustment" namespace="Amikids.TimeTracking" categoryPath="/Amikids.TimeTracking" persistenceName="CompanyCodeAdjustment">
<cf:property name="Id" key="true" />
<cf:property name="PunchCard" typeName="{0}.PunchCard" relationPropertyName="CompanyCodeAdjustments" />
<cf:property name="PunchCardAdjustmentStatus" typeName="{0}.PunchCardAdjustmentStatus" />
<cf:property name="NewValue" />
<cf:property name="CreationUser" set="false" persistent="false" readOnLoad="true" dataMember="false" persistenceName="_trackCreationUser" />
<cf:property name="CreationTimeUtc" set="false" persistent="false" readOnLoad="true" typeName="datetime" dbType="DateTime" dataMember="false" persistenceName="_trackCreationTime" />
<cf:property name="Reason" />
<cf:property name="ReviewedBy" />
<cf:property name="IsVoid" typeName="bool" />
<cf:property name="CompanyName" />
<cf:method name="LoadActiveByPunchCard" body="LOADONE(Amikids.TimeTracking.PunchCard punchCard) WHERE IsVoid = FALSE ORDER BY CreationTimeUtc DESC" />
</cf:entity>
The CodeFluent Query Language (CFQL) provide a special syntax to access special columns such as the creation time column: $column.creationtime. However this is not available in the ORDER BY statement so you must use inline SQL [$Customer{TrackCreationTimeColumn.FullName}$]:
LOAD(datetime now)
WHERE $column.creationtime < #now
ORDER BY [$Customer{TrackCreationTimeColumn.FullName}$]
<cf:entity name="Customer" namespace="Model1">
<cf:property name="Id" key="true" />
<cf:method name="LoadOrderedByCreationDate" body="LOAD(datetime now) WHERE $column.creationtime < #now ORDER BY [$Customer{TrackCreationTimeColumn.FullName}$]" checkLevel="None" />
</cf:entity>
Related
The following entity has a raw method that truncates (deletes) all records in a SQL database. I would like the method to be called from the collection object. Not a game killer if it can't but is it possible?
UserCollection.TruncateDatabase()
instead of
User.TruncateDatabase()
<cf:entity name="User" namespace="Amikids.ActiveDirectoryCache" categoryPath="/Amikids.ActiveDirectoryCache">
<cf:property name="Id" key="true" />
<cf:property name="DirectReports" typeName="{0}.UserCollection" relationPropertyName="ReportsTo" />
<cf:property name="ReportsTo" typeName="{0}.User" relationPropertyName="DirectReports" />
<cf:property name="UserInfo" typeName="{0}.Lightweight.UserInfo" />
<cf:method name="TruncateDataBase">
<cf:body text="RAW" rawText="TRUNCATE TABLE dbo.[User]" language="tsql" />
</cf:method>
<cf:method name="LoadByObjectGuid" body="LOADONE(guid objectGuid) WHERE UserInfo.objectGUID = #objectGuid" />
<cf:method name="LoadByDistinguishedName" body="LOADONE(string distinguishedName) WHERE UserInfo.DistinguishedName = #distinguishedName" />
</cf:entity>
I think you can use a raw delete method: https://www.softfluent.com/Documentation/Methods_Delete.html
<cf:entity name="User">
<cf:method name="TruncateDataBase">
<cf:body text="DELETE() raw" rawBody="TRUNCATE TABLE dbo.[User]" language="tsql" />
</cf:method>
</cf:entity>
My model contains the following entity:
<cf:entity name="SomeEntity">
<cf:property name="Id" key="true" />
<cf:property name="SomeDate" typeName="date?" />
<cf:view name="SomeEntitySummary" autoLightweight="true" checkLevel="none">
<cf:viewProperty name="Id" />
<cf:viewProperty name="SomeDate" nullable="true" typeName="date?" />
</cf:view>
</cf:entity>
The produced code for the SomeEntity class contains a SomeDate property of type
Nullable<DateTime>
However, the produced code for the SomeEntitySummary class contains a SomeDate property of type DateTime and is not nullable.
How can I produce a nullable property in the lightweight entity that is produced for the database view?
CodeFluent Entities infer views from the properties of the entity. So, if the property is nullable, the property of the view should also be nullable. However, it seems there is a small issue, so you must declare the property as modelNullable explicitly (the modeler generates the right xml).
The following model does generate a DateTime? property in the SomeView class:
<cf:entity name="Customer">
<cf:property name="Id" key="true" />
<cf:property name="Name" />
<cf:property name="SomeDate" modelNullable="true" typeName="date" />
<cf:view autoLightweight="true" name="SomeView">
<cf:viewProperty name="Id" />
<cf:viewProperty name="SomeDate" />
</cf:view>
</cf:entity>
What is the proper way to define a reflexive assocation in code fluent.
Given this example, the design shows up correctly, but the generation would struggle with enclosed error message:
Error CF0036: Type for property 'OldEntityA' of entity 'Namespace.EntityA' must be a project entity if 'relationPropertyName' attribute is specified.
<cf:entity name="EntityA" namespace="Namespace" categoryPath="/Category">
<cf:property name="Id" key="true" collectionKey="false" />
<cf:property name="Url" collectionKey="false" />
<cf:property name="OldEntityA" typeName="Namespace.EntityA" relationPropertyName="Unspecified" collectionKey="false" />
Thanks in advance,
You must remove the relationPropertyName attribute or set its value to a valid property name:
<cf:entity name="Category">
<cf:property name="Id" key="true" />
<cf:property name="Name" />
<cf:property name="Parent" typeName="{0}.Category" relationPropertyName="Children" />
<cf:property name="Children" typeName="{0}.CategoryCollection" relationPropertyName="Parent" />
</cf:entity>
I need to know if it is possible to add properties on a many to many Relationship or wether I should go for adding an entity with Relationship ?
In the case of the extra entity, how can I get the two referenced tables to participate in the key (to get a compound key of the two tables) ?
I followed this article but it doesn't go deep enough :http://blog.codefluententities.com/2012/06/14/many-to-many-relationships-with-codefluent-entities/
Thanks in advance,
You have to create an entity with relationship. This new entity has a composite key, so you also have to set setType="List"
<cf:entity name="Student">
<cf:property name="Id" key="true" />
<cf:property name="Name" />
<cf:property name="Enrollments" typeName="{0}.EnrollmentCollection" relationPropertyName="Student" />
</cf:entity>
<cf:entity name="Course">
<cf:property name="Id" key="true" />
<cf:property name="Name" />
<cf:property name="Enrollments" typeName="{0}.EnrollmentCollection" relationPropertyName="Course" />
</cf:entity>
<cf:entity name="Enrollment" setType="List">
<cf:property name="Course" key="true" typeName="{0}.Course" relationPropertyName="Enrollments" />
<cf:property name="Student" key="true" typeName="{0}.Student" relationPropertyName="Enrollments" />
<cf:property name="Prop1" />
<cf:property name="Prop2" />
</cf:entity>
My model contains the following entities:
<cf:entity name="Order" cfom:bindingList="false">
<!--persistenceIdentity is true, because the corresponding column for this property must be auto incremented by the database.-->
<cf:property name="Id" typeName="ulong" key="true" persistenceIdentity="true" cfps:hint="CLUSTERED" />
<!-- composition relation -->
<cf:property name="Orderlines" typeName="{0}.OrderlineCollection" cascadeDelete="Before" cascadeSave="After" />
<cf:method name="Save">
<cf:rule typeName="transaction" transactionType="TransactionScope" timeout="00:60:00" scopeOption="Required" />
</cf:method>
</cf:entity>
<cf:entity name="Orderline" cfom:bindingList="false">
<!--persistenceIdentity is true, because the corresponding column for this property must be auto incremented by the database.-->
<cf:property name="Id" typeName="ulong" key="true" persistenceIdentity="true" cfps:hint="CLUSTERED" />
<!-- Relation back to indicate an 1-to-n composition relationship. -->
<cf:property name="Order" typeName="{0}.Order" />
</cf:entity>
I have the following code:
Order order = new Order();
Orderline orderline = new Orderline();
order.Orderlines.Add(orderline); // ERROR
order.Save(); // Save the order and its orderlines
I get an error when adding the entity to the collection, because the Id property contains the value 0. How can I solve this? I do not want to save the entity before adding it to the collection.
You have to tell CodeFluent that it must use a list instead of a dictionary for the orderlines by means of the setType attribute. After that CodeFluent will no longer use the Id property for the Add and Contains methods, but still checks for the value 0 in the Add method, so you also have to add an OnAfterCreate rule that initializes the Id property:
<cf:entity name="Orderline" cfom:bindingList="false" setType="List">
<!--persistenceIdentity is true, because the corresponding column for this property must be auto incremented by the database.-->
<cf:property name="Id" typeName="ulong" key="true" persistenceIdentity="true" cfps:hint="CLUSTERED" />
<cf:property name="Name" typeName="string" />
<!-- Relation back to indicate an 1-to-n composition relationship. -->
<cf:property name="Order" typeName="{0}.Order" />
<cf:rule typeName="OnAfterCreate" />
<cf:snippet name="OnAfterCreate" language="CSharp">
<!-- here or in a partial class -->
private void OnAfterCreate()
{
this._id = long.MaxValue;
}
</cf:snippet>
</cf:entity>
Now the code works. The orderlines are added and saved within the transaction that is created when saving the order. After saving the order, the orderlines have got their id values from the database:
Order order = new Order();
Orderline orderline = new Orderline();
orderline.Name = "First order";
order.Orderlines.Add(orderline);
orderline = new Orderline();
orderline.Name = "second order";
order.Orderlines.Add(orderline);
order.Save();