Application Factory

Labels
AJAX(112) App Studio(9) Apple(1) Application Builder(245) Application Factory(207) ASP.NET(95) ASP.NET 3.5(45) ASP.NET Code Generator(72) ASP.NET Membership(28) Azure(18) Barcode(2) Barcodes(3) BLOB(18) Business Rules(1) Business Rules/Logic(140) BYOD(13) Caching(2) Calendar(5) Charts(29) Cloud(14) Cloud On Time(2) Cloud On Time for Windows 7(2) Code Generator(54) Collaboration(11) command line(1) Conflict Detection(1) Content Management System(12) COT Tools for Excel(26) CRUD(1) Custom Actions(1) Data Aquarium Framework(122) Data Sheet(9) Data Sources(22) Database Lookups(50) Deployment(22) Designer(178) Device(1) DotNetNuke(12) EASE(20) Email(6) Features(101) Firebird(1) Form Builder(14) Globalization and Localization(6) How To(1) Hypermedia(2) Inline Editing(1) Installation(5) JavaScript(20) Kiosk(1) Low Code(3) Mac(1) Many-To-Many(4) Maps(6) Master/Detail(36) Microservices(4) Mobile(63) Mode Builder(3) Model Builder(3) MySQL(10) Native Apps(5) News(18) OAuth(9) OAuth Scopes(1) OAuth2(13) Offline(20) Offline Apps(4) Offline Sync(5) Oracle(11) PKCE(2) Postgre SQL(1) PostgreSQL(2) PWA(2) QR codes(2) Rapid Application Development(5) Reading Pane(2) Release Notes(184) Reports(48) REST(29) RESTful(29) RESTful Workshop(15) RFID tags(1) SaaS(7) Security(81) SharePoint(12) SPA(6) SQL Anywhere(3) SQL Server(26) SSO(1) Stored Procedure(4) Teamwork(15) Tips and Tricks(87) Tools for Excel(3) Touch UI(93) Transactions(5) Tutorials(183) Universal Windows Platform(3) User Interface(338) Video Tutorial(37) Web 2.0(100) Web App Generator(101) Web Application Generator(607) Web Form Builder(40) Web.Config(9) Workflow(28)
Archive
Blog
Application Factory
Friday, May 11, 2012PrintSubscribe
Improving Efficiency of Output Cache Table

Custom result sets can be produced by stored procedures and web services. A quick look at the sample output cache table and output caching script will give you a few ideas about introducing optimization in the caching.

The datable table CustOrderHist_Cache stores cached output created by concurrent users in the process of interacting with the application. The highlighted columns are the actual output columns produced by the stored procedure.

Sample output cache table designed to work with Northwind.dbo.CustOrderHist stored procedure

The output caching script filters out the data by CacheUserName column to segregate the user-specific result sets. The performance will improve if the column indexed.

The same consideration applies to the column CachExpires.

A single index that includes both CacheUserName and CacheExpires will likely work well in most situations.

The primary key column CacheID is provided to allow selecting data rows in the application user interface. Our sample result set could be changed to use the ProductName  and CustomerID as a compound primary key. It is possible since the stored procedure CustOrderHist produces a list of unique products purchased by a customer. In that case you can delete the CacheID column and simplify the output caching script.

Another area of optimization if the length of time the custom result set remains cached. Most applications will tolerate the data to be “stale” for at least a few minutes if not hours.

The output cache table may end up containing orphan cached data if users are not working with the app on a daily basis. It is a good idea to enhance the caching script with a simple delete statement that wipes out any cached data rows with the cache expiration overdue by a few days.

Sunday, April 29, 2012PrintSubscribe
Automatic Denormalization

Code On Time application generator performs automatic denormalization when constructing application data controllers from tables of a normalized database.

Database architects put a significant effort in creating a normalized database structure. Normalization ensures efficient data storage and maintenance. It is also much easier to extent a normalized database with new tables and columns.

Consider the following subset of tables from the Northwind sample.

Normalized tables Products, Categories, and Suppliers from the Northwind sample

Product information is stored in three tables. Raw product data replaces category and supplier information with ID of records stored in Categories and Suppliers tables.

This is not how the application users see the world. Business users want to see the actual category and supplier when looking at a product record instead of a numeric key value.

Application generator composes the following command text stored in the data controller definition.

<dataController name="Products" . . . .>
  <commands>
    <command id="command1" type="Text">
      <text><![CDATA[
select
    "Products"."ProductID" "ProductID"
    ,"Products"."ProductName" "ProductName"
    ,"Products"."SupplierID" "SupplierID"
    ,"Supplier"."CompanyName" "SupplierCompanyName"
    ,"Products"."CategoryID" "CategoryID"
    ,"Category"."CategoryName" "CategoryCategoryName"
    ,"Products"."QuantityPerUnit" "QuantityPerUnit"
    ,"Products"."UnitPrice" "UnitPrice"
    ,"Products"."UnitsInStock" "UnitsInStock"
    ,"Products"."UnitsOnOrder" "UnitsOnOrder"
    ,"Products"."ReorderLevel" "ReorderLevel"
    ,"Products"."Discontinued" "Discontinued"
from "dbo"."Products" "Products"
    left join "dbo"."Suppliers" "Supplier" on 
      "Products"."SupplierID" = "Supplier"."SupplierID"
    left join "dbo"."Categories" "Category" on 
      "Products"."CategoryID" = "Category"."CategoryID"
]]></text>
    </command>
    . . . . . 

This is the partial output of the query executed in SQL Management Studio.

Output of the data controller command query executed in SQL Management Studio

If you run the sample application then the Products page will be presented in a denormalized user-friendly fashion.

Denormalized presentation of products in the Northwind sample

The actual query executed by application is not the same as text stored in the data controller definition. In fact, the application framework uses the command text as a developer-friendly dictionary to locate at runtime the expressions behind the field names, the base table, and “join” constructs.

This is the actual query text that matches the screen shot.

with page_cte__ as (
    select
        row_number() over (order by "Products"."ProductID") as row_number__
        ,"Products"."ProductName" "ProductName"
        ,"Products"."SupplierID" "SupplierID"
        ,"Products"."CategoryID" "CategoryID"
        ,"Products"."QuantityPerUnit" "QuantityPerUnit"
        ,"Products"."UnitPrice" "UnitPrice"
        ,"Products"."UnitsInStock" "UnitsInStock"
        ,"Products"."UnitsOnOrder" "UnitsOnOrder"
        ,"Products"."ReorderLevel" "ReorderLevel"
        ,"Products"."Discontinued" "Discontinued"
        ,"Products"."ProductID" "ProductID"
        ,"Supplier"."CompanyName" "SupplierCompanyName"
        ,"Category"."CategoryName" "CategoryCategoryName"
    from
    "dbo"."Products" "Products"
        left join "dbo"."Suppliers" "Supplier" on 
            "Products"."SupplierID" = "Supplier"."SupplierID"
        left join "dbo"."Categories" "Category" on 
            "Products"."CategoryID" = "Category"."CategoryID"

    where
    (
    ("Supplier"."CompanyName"=@p0)
    )
)
select * from page_cte__ 
where 
    row_number__ > @PageRangeFirstRowNumber and 
    row_number__ <= @PageRangeLastRowNumber

Notice the use of parameters that prevent any possibility of SQL injection attack.

The SQL statement also utilizes a common table expression for efficient data retrieval.

You can control the inclusion of fields in the data controllers with the help of denormalization field map.

Sunday, April 22, 2012PrintSubscribe
Changing Parent of a Child on Master/Detail Pages

Code On Time web applications automatically hide the foreign key field of a detail data view on master/detail page if the field is used for relationship filtering.

Here is the screen shot that shows a master/detail relationship between Suppliers and Products in the Northwind sample application. Data rows visible in the list of products are linked to the supplier New Orleans Cajun Delights. The application client library hides the column Products.SupplierID to avoid repeating the same value in each child data row.

Master-detail relationship in the Northwind sample created with Code On Time web application generator

Automatic hiding of the foreign key field involved in master/detail filter will maximize the real estate of the page. The side effect of this convenient feature is that it is not possible for a user to change the product supplier by editing a product record in the detail data view. 

A product supplier can be changed if there is a dedicated page of products. Users will have to navigate away to that page. It will also take some time to locate the record in a dedicated view.

Foreign key fields are not hidden in data views if they are not involved in master/detail filtering

Fortunately,  a simple SQL action can be implemented to allow changing the parent of a child record even if the foreign key field is hidden by the master/detail relationship filter.

First, we need to create an action confirmation data controller.

Start the Project Designer and activate the Controllers tab at the top of the designer home page. Select New | New Controller option on the action bar, enter the following properties, and click OK button to save the controller.

Property Value
Name SupplierSelector

Activate the Controllers tab in Project Explorer and right-click the SupplierSelector / Fields node.

Adding a new field to a data controller using Project Explorer

Enter the following properties and save the field by clicking OK button.

Property Value
Name ProductName
Type String
Code Default
SelectFieldValue("Context_ProductName")
Label Product
Values of this field cannot be edited Yes

Create two more fields – SupplierCompanyName and SupplierID.

Properties of the field SupplierCompanyName.

Property Value
Name SupplierCompanyName
Type String
Code Default
SelectFieldValue("Context_SupplierCompanyName")
Label Supplier
Values of this field cannot be edited Yes

Properties of the field SupplierID.

Property Value
Name SupplierID
Type String
Label New Supplier
Items Style Lookup
Items Data Controller Suppliers
Data Value Field SupplierID
Data Text Field CompanyName

The hierarchy of the SupplierSelector node shall look as follows.

The hierarchy of the 'SupplierSelector' data controller node in Project Explorer

The SupplierSelector data controller allows collecting a new Supplier ID.

Now we need to define a new SQL action in the Products data controller and use SupplierSelector as a modal confirmation form.

Right-click Products / Actions / ag1 (Grid) action group node on the Controllers tab in the Project Explorer and select the New Action option in the context menu.

Adding a new action to a group with 'Grid' scope in a web app created with Code On Time web application generator

Enter the following values in the action properties and click OK button to save the changes.

Property Value
Command Name SQL
Header Text Change Supplier
Data
update Products
set SupplierID = @Parameters_SupplierID
where ProductID = @ProductID
Confirmation

_controller=SupplierSelector
_title=Select a New Product Supplier
_width=500

Click Browse on the Project Designer toolbar, navigate to the Suppliers page when the application opens in your default web browser. Open the context menu of any product and select Change Supplier option in the context menu of the product data row.

Activating a custom 'SQL' action in the context menu of a data row in Code On Time web application

The modal action confirmation will show up. Select a new supplier and click OK button to execute the action.

Modal action confirmation forms allow easy collection of parameters from the application end users

The product will disappear from the detail view. You will find it liked to the supplier record selected in the action confirmation form.

The product data row is now linked to another supplier selected in the modal action confirmation form

It is easy to access the values of fields entered in the action confirmation.

Action Change Supplier defines the following SQL script.

update Products
set SupplierID = @Parameters_SupplierID
where ProductID = @ProductID

Simply prefix the field name from the action confirmation data controller with “Parameters_”. The action implementation updates the SupplierID of selected product with the value selected in the modal confirmation.

If you are implementing custom business rules or shared business rules then you can access the values of action parameters as fields with the same “Parameters_” prefix.

Modal confirmation shows the name and current supplier of the selected product. Both fields are configured as read-only and use a similar Code Default expression. Here the expression from the SupplierSelector.SupplierCompanyName field.

SelectFieldValue("Context_SupplierCompanyName")

This code works with both C# and Visual Basic. The prefix “Context_” allows the action confirmation data controller business rules to access the field values of the controller that will be effected by the action. In our example, the name “Context_SupplierCompanyName” is referring to the SupplierCompanyName field of  Products data controller.