SQL Server

Labels
AJAX(112) App Studio(7) 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(177) 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(183) 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(2) 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
SQL Server
Wednesday, February 13, 2013PrintSubscribe
“Filter Expression” Property of Views

The “Filter Expression” property allows limiting the records displayed in a specific view by an SQL compatible logical expression.

The default Orders grid view in a sample Northwind web application displays all orders.

List of all orders.

Let’s create a new view by the name of “Orders This Month” that will only display orders placed in the current month.

Start the Project Designer. In the Project Explorer, switch to the Controllers tab. Right-click on Orders / Views / grid1 node, and press Copy.

Copying 'grid1' view of Orders controllers.

Right-click on Views, and press Paste. A duplicate of view “grid1” will be created.

Pasting onto Views node of Orders controller.      Duplicate of 'grid1' view, called 'v100' has been created.

The properties screen for the new view will be open in the Project Browser. Make the following changes:

Property New Value
Label Orders This Month
Filter Expression $thismonth(OrderDate)

Press OK to save. Double-click on Orders / Views / grid1 node.

View 'grid1' of Orders controller.

Change the label:

Property New Value
Label All Orders

Press OK to save. On the toolbar, press Browse.

Navigate to the Orders page. The All Orders view will continue to display an unfiltered list of orders.

The default grid view of Orders displaying an unfiltered list.

Use the View Selector dropdown in the top-right corner to switch to the Orders This Month view. Only orders placed in the current month will be displayed.

A list of orders filtered in the current month.

When the command is configured in order to retrieve data from the database, the Filter Expression is parsed by the application framework and any standard filter operators will be replaced by the SQL equivalent. SQL compatible logical expressions may also be used. In the example above, the filter is passed to the application framework as the following:

$thismonth(OrderDate)

The framework converts the filter to the following where expression.

"Orders"."OrderDate" between @p0 and @p1

This expression is then inserted into the select command and passed to the server.

with page_cte__ as (
select
row_number() over (order by "Orders"."OrderID") as row_number__
,"Orders"."CustomerID" "CustomerID"
,"Orders"."EmployeeID" "EmployeeID"
,"Orders"."OrderDate" "OrderDate"
,"Orders"."RequiredDate" "RequiredDate"
,"Orders"."ShippedDate" "ShippedDate"
,"Orders"."ShipVia" "ShipVia"
,"Orders"."Freight" "Freight"
,"Orders"."ShipName" "ShipName"
,"Orders"."ShipAddress" "ShipAddress"
,"Orders"."ShipCity" "ShipCity"
,"Orders"."OrderID" "OrderID"
,"Customer"."CompanyName" "CustomerCompanyName"
,"Employee"."LastName" "EmployeeLastName"
,"ShipVia"."CompanyName" "ShipViaCompanyName"
from
"dbo"."Orders" "Orders"
    left join "dbo"."Customers" "Customer" on "Orders"."CustomerID" = "Customer"."CustomerID"
    left join "dbo"."Employees" "Employee" on "Orders"."EmployeeID" = "Employee"."EmployeeID"
    left join "dbo"."Shippers" "ShipVia" on "Orders"."ShipVia" = "ShipVia"."ShipperID"

where
(
("Orders"."OrderDate" between @p0 and @p1)
)
select * from page_cte__ where row_number__ > @PageRangeFirstRowNumber 
    and row_number__ <= @PageRangeLastRowNumber
Sunday, January 13, 2013PrintSubscribe
Validation with SQL Business Rules

It is a requirement for every database web application to perform data validation. SQL business rules can be used to extend the functionality of basic database validation to ensure that the user enters values that conform to business requirements.

Server-side validation has the benefit of direct access to database and sophisticated APIs of the server-side operating system and database engine. One major limitation is the inability to have a conversation with the user – the server-side code cannot ask questions of the user without complex chained internet callbacks. If the business rule implementation requires confirming certain aspects of validation by directly requesting information from the application user, then a validating JavaScript business rule must be implemented. If a “conversational” validation business logic requires access to the database, then consider utilizing the RESTful application server of your web app.

Consider the following example below. The default Northwind web application allows users to select a product and enter any unit price, quantity, and discount. The database engine will validate the constraints and raise an exception if an error occurs.

Basic database engine validation in action.

However, the database server will not test for logical violations, such as absurd unit price or quantity.

Let’s implement an SQL business rule that will perform multi-step validation.

Configuring Fields

Start the Project Designer. Switch to the Controllers tab in the Project Explorer. Double-click on OrderDetails / Fields / ProductID* (Int32) –> Products node.

Field 'ProductID' of Order Details controller.

Change the following:

Property Value
Copy UnitPrice=UnitPrice

Press OK to save. Next, double-click on UnitPrice* (Decimal) field node.

'UnitPrice' field of Order Details controller.

Make the following changes:

Property Value
The value of this field is calculated by a business rule expression. true
Context Fields ProductID, UnitPrice, Quantity, Discount

Press OK to save.

Configuring Business Rule

Right-click on OrderDetails / Business Rules node, and press New Business Rule.

Creating a new business rule for OrderDetails controller.

Assign the following values:

Property Value
Type SQL
Command Name Calculate|Insert|Update
Phase Execute

Paste in the following script:

-- 1. If the collected values are not valid then do not enforce the rule.
--    The client library will instruct the user to correct the input.
declare @Success nvarchar (5) = 'true'

-- 2. Reset the base price for calculation of price limits
--    if the product selection has changed or if an existing
--    data row has been selected for editing
if (@ProductID != @Session_ProductID or @Session_ProductID is null)
begin
    declare @BasePrice decimal = @UnitPrice
    if (@Arguments_Trigger != 'ProductID')
    begin
        set @BasePrice = @UnitPrice_OldValue
    end
    set @Session_UnitPrice = @BasePrice
    set @Session_ProductID = @ProductID
    if (@Arguments_Trigger = 'ProductID')
    begin
        set @Quantity = 1
        set @Discount = 0
        set @Result_Focus = 'Quantity'
    end
end

-- 3. Adjusting base price for an existing record
declare @OriginalUnitPrice float = @Session_UnitPrice
if (@Session_UnitPrice is null)
begin
    set @OriginalUnitPrice = @UnitPrice_OldValue
    set @Session_UnitPrice = @OriginalUnitPrice
end

-- 4. Validate Unit Price Field
declare @MinPrice float = @OriginalUnitPrice
declare @MaxPrice float = (@OriginalUnitPrice * 1.05)
if (@UnitPrice is null)
    set @Result_Focus = 'UnitPrice, Please enter the price.'
else
    if (@UnitPrice < @MinPrice or @UnitPrice >= @MaxPrice)
        set @Result_Focus = 'UnitPrice, The price must be between $' 
                        + cast(convert(money, @MinPrice) as nvarchar(50)) + ' and $' 
                        + cast(convert(money, @MaxPrice) as nvarchar(50)) + '.'
        set @Success = 'false'

-- 5. Validate Quantity Field
if (@Quantity is not null and @Quantity <= 0)
begin
    set @Result_Focus = 'Quantity, The quantity must be greater than zero.'
    set @Success = 'false'
end

-- 6. Validate Discount Field
if (@Discount > 1)
    set @Discount = (@Discount / 100)

-- 7. Confirm Discount is between 0.00 and 0.99
if (@Discount is not null and (@Discount < 0.00 or @Discount > 0.99))
begin
    set @Result_Focus = 'Discount, The discount must be between 0.00 and 0.99 (0% - 99%).'
    set @Success = 'false'
end

-- 8. Wrapping up
if (@Arguments_CommandName = 'Calculate' or @Success = 'false')
    set @BusinessRules_PreventDefault = 1

The business rule will be fired when a user inserts a new record, updates an existing record, and every time a field value is changed. The client library will first ensure that the values are valid. Then the script will be sent to the database server. The field values are bound by the application framework as @FieldName. Session variables are introduced to the web application by using @Session_FieldName. The name of the field that triggered the command is recorded in @Arguments_Trigger, and the command is saved in @Arguments_Command. The client library is instructed to display messages next to fields using @Result_Focus. The parameter @BusinessRules_PreventDefault will prevent the default behavior of the web application from continuing.

There are eight distinct steps to this business rule:

1. Initial Input Validation

When a user enters an invalid value in the Order Details form, the client library will display an error and prevent execution of the business rule – no code needs to be written for this to occur.

The variable @Success is declared in order to remember the status of validation. By default, it is set to “true”. If any of the later steps fail to validate, this variable will be changed to “false” and the last step will ensure that the user cannot apply changes.

declare @Success nvarchar (5) = 'true'

The picture below shows an example of automatic client-side validation.

Example of automatic client-side validation.

2. Determination of the “Base” Price

This query will memorize the last ProductID and UnitPrice values in session variables, as well as the UnitPrice of the selected product when it is copied over. This UnitPrice will be saved as @BasePrice, and will be used to prevent price inflation by more than 5%. When the ProductID is changed, the Quantity and Discount fields will be reset to default values of 1 and 0.

if (@ProductID != @Session_ProductID or @Session_ProductID is null)
begin
    declare @BasePrice decimal = @UnitPrice
    if (@Arguments_Trigger != 'ProductID')
    begin
        set @BasePrice = @UnitPrice_OldValue
    end
    set @Session_UnitPrice = @BasePrice
    set @Session_ProductID = @ProductID
    if (@Arguments_Trigger = 'ProductID')
    begin
        set @Quantity = 1
        set @Discount = 0
        set @Result_Focus = 'Quantity'
    end
end

The screenshot below shows the form after the product has been changed.

Selecting a new product will reset Unit Price, Quantity, and Discount.

3. Adjusting Base Price for Existing Records

If the user is editing an existing record, then the original UnitPrice value is memorized using a session variable.

declare @OriginalUnitPrice float = @Session_UnitPrice
if (@Session_UnitPrice is null)
begin
    set @OriginalUnitPrice = @UnitPrice_OldValue
    set @Session_UnitPrice = @OriginalUnitPrice
end

4. Price Validation

The minimum and maximum price is calculated. If the price is blank, the user is directed to enter a value. If the price is out of range, the user is forced to correct the problem.

declare @MinPrice float = @OriginalUnitPrice
declare @MaxPrice float = (@OriginalUnitPrice * 1.05)
if (@UnitPrice is null)
    set @Result_Focus = 'UnitPrice, Please enter the price.'
else
    if (@UnitPrice < @MinPrice or @UnitPrice >= @MaxPrice)
        set @Result_Focus = 'UnitPrice, The price must be between ' 
                        + cast(@MinPrice as nvarchar(50)) + ' and ' 
                        + cast(@MaxPrice as nvarchar(50)) + '.'
        set @Success = 'false'

The form below shows price validation in action.

Price validation in form view on Unit Price field.

Here is validation in data sheet view.

Price validation in Order Details data sheet view.

5. Quantity Validation

Validation will ensure that a positive value is entered into Quantity field.

if (@Quantity is not null and @Quantity <= 0)
begin
    set @Result_Focus = 'Quantity, The quantity must be greater than zero.'
    set @Success = 'false'
end
Validation of a positive integer in Quantity field.

6. Automatic Conversion of Discount

When the user enters a value greater than 1, the business rule will automatically convert the value to a fraction of 100.

if (@Discount > 1)
    set @Discount = (@Discount / 100)

For example, a value of “25” has been entered in the New Order Details screen shown below.

Discount field value of '25' is entered.

When focus is shifted from the field, the value is converted to a percentage.

The value of Discount is converted into a percentage.

7. Discount Range Validation

A validation error will be displayed if the Discount value is not within range after automatic conversion.

if (@Discount is not null and (@Discount < 0.00 or @Discount > 0.99))
begin
    set @Result_Focus = 'Discount, The discount must be between 0.00 and 0.99 (0% - 99%).'
    set @Success = 'false'
end
Percentage validation of 'Discount' field.

8. Wrapping Up

The default behavior of the application server will be to continue processing the Insert or Update action triggered by the user. If any of the validations have failed or the command was Calculate, the default behavior will be halted.

-- 8. Wrapping up
if (@Arguments_CommandName = 'Calculate' or @Success = 'false')
    set @BusinessRules_PreventDefault = 1
Tuesday, November 27, 2012PrintSubscribe
Advanced User Manager for Custom Membership and Role Provider: Configuring the Views

Let’s customize the Users page and views in order to improve the presentation of the User Management screen.

Moving the Users Page

Start the Project Designer. In the Project Explorer, drag Region / Roles page node onto Region / Users page node to place it underneath Users page.

Dropping Roles page node onto Users page node.      Roles page node has been placed underneath Users page.

Drag Region / Users node on the right side of Reports node to place it at the bottom of the hierarchy.

Dropping Users page node on the right side of Reports page node.      Users page has been placed after Reports.

Right-click on Users / container2 node, and press Delete.

Deleting 'container2' on the Users page.

Configuring grid1

Switch to the Controllers tab and expand to Users / Views / grid1 node. While holding Ctrl key, select the data fields in the following order: UserName, IsApproved, Email, IsLockedOut, CreationDate, LastLoginDate, and Comment. Drop the data fields on Users / Views / grid1 to sort the fields in the selected order.

Dropping several data fields onto 'grid1' view.      The data fields have been rearranged.

Select the data fields LastActivityDate and LastLockedOutDate. Right-click and press Delete.

Deleteing data fields 'LastActivityDate' and 'LastLockedOutDate'.

Configuring editForm1

Double-click on Users / Views / editForm1 / c1 – Users category node.

The category 'c1 - Users' of editForm1 view.

Change the following properties:

Property New Value
Header Text User Information
Description Please select user roles that most closely match user's responsibilities. Roles control access to the areas of this web site. Please contact system administrator if role access restrictions must be changed. Enter any additional comments about this user account. Comment is not visible to the user.

Press OK to save. Right-click on Users / Views / editForm1 node, and press New Category.

New Category context mneu option for editForm1 view.

Assign the following values:

Property New Value
Header Text Password Recovery
Description During the recovery of a forgotten password the user will be asked to enter a user name. If a user account exists then a security question is requested to be answered. A correct answer will trigger an email with a temporary password send to the user. Change locked out flag to 'No' if the user has been locked out after reaching a maximum number of failed login attempts and you want to allow user to login again.

Press OK to save. Expand Users / Views / editForm1 / c1 – User Information category node. While holding Ctrl key, select the following data fields: Email, Password Question, and IsLockedOut. Drop the data fields onto Users / Views / editForm1 / c2 – Password Recovery node.

Dropping several data fields onto category 'c2 - Password Recovery'.      Data fields have been moved to category 'c2 - Password Recovery'.

Press OK to save. Create another category with these properties:

Property New Value
Header Text Activity Statistics
Description Shows statistics of user activity.

Save the category. Drag the data fields CreationDate, LastLoginDate, LastActivityDate, and LastPasswordChangedDate onto Users / Views / editForm1 / c3 – Activity Statistics.

Dropping several data fields onto category 'c3 - Activity Statistics'.      Data fields have been moved to category 'c3 - Activity Statistics'.

Create one more category:

Property New Value
Header Text Login Statistics
Description These are the statistics of failed login attempts by this user. User will be locked out after reaching a maximum number of failed login attempts. Locked out users will be able to login again after the date in Failed Password Attempt Window Start. Users who failed to recover the password will be able to so after the date in Failed Password Answer Attempt Window Start. You can restore user's ability to login by setting Locked Out flag to 'No'.

Save the category. Drag the data fields LastLockedOutDate, FailedPasswordAttemptCount, FailedPasswordAttemptWindowStart, FailedPasswordAnswerAttemptCount, and FailedPasswordAnswerAttemptWindowStart onto Users / Views / editForm1 / c4 – Login Statistics category node.

Dropping several data fields onto category 'c4 - Login Statistics'.      Data fields have been moved to category 'c4 - Login Statistics'.

Select the data fields Password and PasswordAnswer. Right-click, and press Delete.

Deleting the data fields 'Password' and 'PasswordAnswer'.

Configuring createForm1

Double-click on Users / Views / createForm1 / c1 – New Users category node.

Category 'c1 - New Users' of createForm1 view.

Change the following properties:

Property New Value
Header Text New User Information
Description Please enter user name and password. Note that password must be at least 7 characters long and include one non-alphanumeric character. Only approved users will be able to login into the website.

Press OK to save. Right-click on Users / Views / createForm1 node, and press New Category.

New Category context mneu option for 'createForm1' view.

Assign the following values:

Property New Value
Header Text Roles
Description Please select user roles that most closely match user's responsibilities. Roles control access to the areas of this web site. Please contact system administrator if role access restrictions must be changed.

Press OK to save. The Roles field will be added in the next tutorial.

Create another category with these properties:

Property New Value
Header Text Password Recovery
Description These fields are required to help a user to recover a forgotten password. During the recovery process the user will be asked to enter a user name. If a user account exists then a security question is requested to be answered. A correct answer will trigger an email with a temporary password send to the user.

Save the category. Drag the data fields Email, PasswordQuestion, and PasswordAnswer onto Users / Views / createForm1 / c3 – Password Recovery.

Dropping several data fields onto category 'c3 - Password Recovery'.     Data fields moved to category 'c3 - Password Recovery'.

Create one more category:

Property New Value
Header Text Comments
Description Enter any additional comments about this user account. Comment is not visible to the user.

Save the category. Drag the data field Comment onto Users / Views / createForm1 / c4 – Comments category node.

Several data fields dropped onto category 'c4 - Comments'.     Data fields moved to category 'c4 - Comments'.

Click on the data field LastActivityDate. While holding Shift key, click on the data field FailedPasswordAnswerAttemptWindowStart. Right-click, and press Delete.

Deleting the unnecessary data fields from createForm1 view.

Configuring Read-Only Fields and Checkboxes

Right-click on Users / Fields node, and press List.

The 'List' option for Fields node of Users controller.

Make the following changes to the list of fields:

Name Read Only Items Style Data Format String
IsApproved   Check Box  
LastActivityDate Yes   g
LastLoginDate Yes   g
LastPasswordChangedDate Yes   g
CreationDate Yes   g
IsLockedOut   Check Box  
LastLockedOutDate Yes   g
FailedPasswordAttemptCount Yes    
FailedPasswordAttemptWindowStart Yes   g
FailedPasswordAnswerAttemptCount Yes    
FailedPasswordAnswerAttemptWindowStart Yes   g

Double-click on Users / Views / editForm1 / c1 – User Information / UserName data field.

UserName data field node of 'editForm1' of Users controller.

Change the Read Only property:

Property New Value
Read Only Yes

Press OK to save. Double-click on Users / Views / editForm1 / c2 – Password Recovery / PasswordQuestion data field.

PasswordQuestion data field node of 'editForm1' of Users controller.

Change the Read Only property:

Property New Value
Read Only Yes

Press OK to save. Double-click on Users / Views / createForm1 / c1 – New User Information / Password data field node. Make the following change:

Property New Value
Text Mode Password

Save the data field.