Search This Blog

Showing posts with label business logic. Show all posts
Showing posts with label business logic. Show all posts

Tuesday, October 10, 2017

ImmediatePostData attribute support in XAF Mobile v17.1.7

I am happy to inform you that starting with version 17.1.7, XAF Mobile (CTP) supports ImmediatePostDataAttribute. You can see how it works in action using our https://demos.devexpress.com/XAF/MainDemoMobile/ demo in the Payment object's View. 


You are welcome to download the latest version and test this feature in scenarios you are interested in. As usual, your feedback is greatly appreciated. Do not hesitate to submit tickets in our Support Center.

NOTE: Automatic updates will not work for non-persistent calculated reference properties due to an OData specificity.

Monday, December 12, 2016

Implementing State Machines at the Business Object vs Controller levels - YOUR FEEDBACK IS NEEDED!!!

I wanted to seriously question the current approach for declaring state machines in code using the StateMachine<T> class and IState/IStateMachineProvider interfaces (Predefined State Transitions Created in Code) and hear what you think of it in general. The main reasons behind this interest are the limitations this originally implemented approach has compared to other available solutions and hence associated support costs.



"Yet Another Controller"© 
In fact, in certain scenarios, creating a custom Controller with the SingleChoiceAction Action or a set of SimpleAction Actions can be simpler and more straightforward than defining a coded State Machine at a domain level. To give you a concrete example of such an alternative solution, check out this Controller that eventually does the same thing as the code in the original documentation article above, but with old-good SimpleAction objects manipulated on View and other suitable events. You can find another example with a SingleChoiceAction in this test project (it's from this SC ticket, so process it with the Project Converter tool first). Even though the alternative Controller-based approach requires more code, it allows you to provide a more granular control over created states and their visual representations. It is cleaner and easier to understand/extend for other business requirements, because it is your own code that uses only the basic XAF APIs.


Implications of using the questioned approach
Contrary to that, the questioned approach is really a bit shorter with the help of 'state', 'transition' and 'state appearance' abstractions defined near your business class, but everything has its own trade offs.

Monday, June 6, 2016

How to access derived (inherited) objects from OData Service

I want to quote a new KB article we created to more easily answer such user questions, especially due to the increased interest in OData in light of the recent arrival of the XAF mobile UI (CTP)

Scenario/Situation
"I created an XPO OData service (XpoDataServiceV3) based on my model, but when I try to query a collection of objects that are derived from another persistent object, the result set includes all objects inherited from the base class. Is it a bug? How can I get only derived objects?"

Explanation/Solution
"This behavior is caused by limited support for derived objects in the OData protocol, which doesn't expose derived classes as entity sets. To access derived objects or their properties, you have to include a type cast using the qualified object type name in the path constructed for a base class. For example, if you wish to get Person objects that are inherited from Party, use the following query:

http://localhost:56789/MyDataService.svc/Party/Person/



Please refer to Derived Entity Type section of the OData Advanced Tutorial and Addressing Derived Types section of the OData protocol documentation for more examples.

Note that this specificity is not related to XPO. If you create a WCF Data Service based on an Entity Framework model, it will behave in a similar manner in regard to derived entities."



And here is a real-life URL query I tested with the data service I created with our MainDemo app and the new Mobile project template:

http://localhost:51562/DataService.svc/DevExpress_Persistent_BaseImpl_Task/MainDemo_Module_BusinessObjects_DemoTask?$filter=Subject%20eq%20%27Task1%27


Again, take special note that this is however, NOT specific to XAF itself or DevExpress ORM OData Service in any way, but rather to the OData V3 protocol itself.


Thursday, March 3, 2016

How to perform CRUD operations with non-persistent objects using standard XAF forms

This post is about our putting a continuous effort into improving XAF developer usability in scenarios requiring manipulation of non-persistent objects or POCOs. Typical scenarios relying on such non-persistent classes include all sorts of confirmation dialogs, user input forms with parameters, lists with temporary data, analysis and reporting data obtained from dynamic runtime calculations, stored procedures (SP), arbitrary SQL queries or third-party services or anything that needs a standard XAF CRUD UI (and, of course, extra modules), but does not require object state to be eventually persisted to the database.

As you probably know, XAF was primarily designed for automatic UI generation tied to one of the two supported persistence layers or ORM technologies - XPO and Entity Framework. Don't get me wrong here: binding standard XAF forms to temporary non-persistent data was always possible (and there are many standard XAF pieces are implemented with it: logon, change the password, about, validation, notification dialogs, etc.), but the number of supported scenarios was quite limited previously. For instance, a year ago there was no really straightforward way of binding a non-persistent list of objects to a ListView directly. It required creating an intermediate non-persistent class holding a collection of non-persistent objects and then showing its DetailView (learn more on this former approach...).

So that is where NonPersistentObjectSpaceProvider, NonPersistentObjectSpace and its ObjectsGetting event first came to the rescue in v15.1 to simplify the lives of XAF developers (learn more...). The current v15.2 brought it to the next level by allowing standard XAF CRUD commands (the New, Delete and Save Actions) for non-persistent objects. The ModifiedObjects property of the NonPersistentObjectSpace class provides access to all created, deleted and modified objects within its scope, unless the IObjectSpace.CommitChangesIObjectSpace.Refresh or IObjectSpace.Rollback methods are called. Step-by-step instructions for implementing this functionality in your XAF v15.2.4+ project are now provided in the online product documentation:

How to: Perform CRUD Operations with Non-Persistent Objects

And here are a couple of screenshots showing what it can look like in the UI*:


Monday, December 21, 2015

Avoid auto-saving a master when a new non-aggregated child is created and making the New Action available for many-to-many lists

In v15.2.4 we have added the LinkNewObjectToParentImmediately property to the XafApplication and NewObjectViewController classes. 

By default, XafApplication.LinkNewObjectToParentImmediately is set to true to keep the behavior of existing applications unchanged (a new object linked to the master object is created and the master object is committed when the New action is executed in the nested List View). However, in new applications created in the 15.2 version, the default value is overridden to false in code generated by the Solution Wizard.

Use XafApplication.LinkNewObjectToParentImmediately to change the behavior globally (note that this property is hidden in the Application Designer and you can set it only in code). Use NewObjectViewController.LinkNewObjectToParentImmediately to change the behavior for a specific View. The behavior of aggregated collections is not changed.

There are several positive results from this LinkNewObjectToParentImmediately = false change:
1. A reference to the master object is visible in the new child object immediately. 
2. The master object is not committed and the link is not created when the New action is executed in the nested List View. At the database level that means that the reference to the master table is not added to the new child record immediately. The link is created later when the child object is committed. To keep the link, a user should save the master object; otherwise, the unlinked child object will be saved.
3. The New Action is now available directly in the nested ListView or the Link dialog for many-to-many XPO associations!

There were a lot of customer requests for the last two things, so I hope you will like this news. Please let me know what you think in comments.



Monday, December 14, 2015

How to hide or filter out certain types from the drop-down editor for the System.Type properties

I want to share my recent article on the subject that demonstrates yet another example of how flexible and powerful XAF really is. There, I will describe three possible ways of accomplishing the same task, starting with the most recommended platform-agnostic solution at the business model level (write once, work everywhere) and finishing by manipulating end control properties in the UI for certain platforms and contexts. 


So, let me quite myself from this KB article in our Support Center:

Monday, August 24, 2015

A more straightforward and convenient way to query data using LINQ with ObjectSpace

First of all, it is important to note that the capability to query data using LINQ has been available for a long time in the current version of XAF (or better said, in the underlying Entity Framework and XPO ORM libraries). So, this improvement in v15.2 is all about improving developer usability by exposing a helper method for the IObjectSpace interface representing one of the main XAF entities (learn more...). 

As noted in the corresponding SC ticket (from here you can also learn on the current solution):

The IObjectSpace interface now declares the following method:

[C#]IQueryable<T> GetObjectsQuery<T>(Boolean inTransaction = false);
This method is implemented in the XPObjectSpaceEFObjectSpace and NonPersistentObjectSpace classes. 
The inTransaction parameter has effect in XPO only and enables the mode in which querying a data store for objects includes all in-memory changes into query results.
In the NonPersistentObjectSpace, the GetObjectsQuery method casts the collection of objects created in the ObjectsGetting event to IQueryable and returns the result.

For XPObjectSpace, this method just returns a new XPQuery<T> from the underlying Session, while for the EFObjectSpace, the GetObjectsQuery method returns a new instance of ObjectQuery<T> with the help of the associated DbContext.

Here are a few usage examples from our unit tests (using the method-based query syntax):
EF:
IQueryable<Product> objectsQuery = objectSpaceB.GetObjectsQuery<Product>().Where(p => (p.Supplier.ID == supplier_A.ID));
Assert.AreEqual(5, objectsQuery.Count());
Assert.AreEqual(3, objectsQuery.Where(p => (p.Name == "A")).Count());
Assert.AreEqual(2, objectsQuery.Where(p => (p.Name == "B")).Count());

XPO:
IQueryable<TestObject> query = objectSpaceB.GetObjectsQuery<TestObject>();
Assert.AreEqual(5, query.Count());
Assert.AreEqual(3, query.Where(t => t.StringProperty == "A").Count());
Assert.AreEqual(2, query.Where(t => t.StringProperty == "B").Count());

I hope you will appreciate this minor improvement and it will save you from polluting your code by the casts to the XPObjectSpace/EFObjectSpace types to access the underlying ORM data context LINQ features.

Wednesday, March 25, 2015

Determining whether a security user belongs to a certain role in code becomes a bit easier

As you probably know, we already have a built-in solution for checking this condition within criteria - IsCurrentUserInRole criteria function (learn more from my blog...).
Doing the same in C# or VB.NET code is also possible with LINQ or a simple 'foreach' (through the SecuritySystem singleton), it would still be great to have a more straightforward and built-in method for this common task, especially for newbies.

Good news is that starting with version 14.2.7, this task can be done more easily. Let me quote the provided solution details from this Support Center thread:

Now, you can determine whether a user belongs to a certain role in code using the IsUserInRole extension method. This method is available for both ISecurityUserWithRoles (new Security System) and IUserWithRoles (legacy Security System) user types.


Thursday, March 19, 2015

Making sure a property value is unique with XAF and XPO

I wanted to share a link to a hot Support Center discussion on the subject (it has now been unpublished by the author, sorry) with the community members as I believe this business task is not unique:-) and many others should be interested in knowing how to properly handle this.
I am going to detail technical considerations of possible solutions at the application UI and database levels depending on various configurations of your data model including inheritance mapping options (Table per Hierarchy or Table per Type) and soft deletion.

Application UI level

First of all, let's start from the UI part. How would a developer of an XAF app ensure that its end-users are not allowed to save records whose property value or combination of values are unique? 
As you know, XAF ships with a built-in validation module that provides a powerful and extendable validation engine and a large set of predefined attributes to configure common validation rules declaratively. To ensure uniqueness, you can first add the ValidationModule component into your XAF module or application via the designers and then choose from the two built-in rules: RuleCombinationOfPropertiesIsUnique and RuleUniqueValue (it is also possible to turn RuleObjectExists and RuleFromBoolPropert for the same task, but its use is not that straightforward use and I will not talk about it for now). Depending on your preferences, you can either annotate your data model classes with the corresponding code attributes, e.g.:

       [RuleUniqueValue]

       public string Name { ... }


or declare everything at the Application Model level via the Model Editor tool (learn more...). In addition, you can configure the rule's CriteriaEvaluationBehavior parameter, to specify whether to look for modified objects that are currently loaded in memory, in addition to objects in the database itself.
As a result, the XAF's validation engine will consider the rules you configured  when a data record is being saved (technically, when the View.ObjectSpace.Committing event is raised) and will throw ValidationException when uniqueness is violated. This is a special exception type, which is caught by other system controllers to display the validation error in a nice way in the UI:




This would be our topmost  or basic protection level as it handles user input only. It will not help avoid duplicates if the same data records are created in code by a developer who did not call one of the Validator.RuleSet.ValidateXXX methods. 

Tuesday, March 3, 2015

Simplifying declaration of calculated properties in code for DataView mode with Entity Framework

Starting with v14.2.4 (and even 14.1.9) you can use the DevExpress.ExpressApp.DC.CalculatedAttribute to specify an expression used to calculate a property value of an Entity Framework class in Data View mode:
[C#]
public class Payment { public Int32 ID { get; protected set; } public Decimal Rate { get; set; } public Decimal Hours { { get; set; } [NotMapped, DevExpress.ExpressApp.DC.Calculated("Rate * Hours")] public Decimal CalculatedAmount { get { return Rate * Hours; } }
   // Other data properties and logic...
}
This attribute functions exactly like the DevExpress.Xpo.PersistentAlias attribute applied to a regular business class property. Of course, properties, referenced in the specified expression (using our cross-platform object-oriented criteria language) should be persistent to be able to run an SQL query at the database level. 

To remind you of the DataView mode, this is what you will see in the SQL Server Profiler if you set DataAccessMode = DataView for the Payment_ListView node containing only the Amount column above:

SQL:
SELECT 
    [Limit1].[ID] AS [ID], 
    [Limit1].[C1] AS [C1]
    FROM ( SELECT TOP (2147483647) 
        [Extent1].[ID] AS [ID], 
        [Extent1].[Rate] * [Extent1].[Hours] AS [C1]
        FROM [dbo].[Payments] AS [Extent1]
    )  AS [Limit1]

Note that even though our entity may contain a way more other persistent properties, the query included only the two from the expression above, which increases performance in certain scenarios.
The advantage of this attribute solution is that it is easier to keep your data model logic in one place/class instead of spreading it across multiple layers, e.g., Application Model, where the DataView settings are specified:

XAFML:
<ListView Id="Payment_ListView" DataAccessMode="DataView">
    <Columns>
       <ColumnInfo PropertyName="CalculatedAmount" IsNewNode="True" />
    </Columns>
</ListView>




If you are not sure of which ListView data access mode is best for your particular screen, these guidelines in our docs will help you decide.

Thursday, February 26, 2015

How to implement and where to put business logic in XAF?

We have recently rolled out another update of our online documentation where we isolated and detailed one of the most common questions beginners have. Actually, the answer was already present in the docs, KBs and examples and we have just reorganized these learning materials so that you need to know is in one place.

Please be sure to check out the new concepts section at eXpressApp Framework > Concepts > Data Manipulation and Business Logic even if you are an experienced XAFer. This is not the final version and we have several updates planned for this section in the near future.


If you are getting started with the framework, then running through the eXpressApp Framework > Getting Started > Basic Tutorial (SimpleProjectManager Application) tutorial will be a prerequisite.

I also want to remind you that our What's New documents for new product versions include the lists of documentation changes (What's New In Help) where you can find other interesting stuff like this, e.g.: this is what we have in v14.2.5 for XAF.

Please let me know what you think in comments to this blog. Thanks in advance!

Friday, December 26, 2014

An Entity Framework version of our XCRM demo

You might have noticed that starting with v14.2 we made an EF-based version of our popular XCRM show-case demo. It is installed at %PUBLIC%\Documents\DevExpress Demos 14.2\Components\eXpressApp Framework\XCRM\ by default.


Data models and DbContext code are located within the XCRM.Module\Data\ folder for you to explore. These data models are built for real and quite complex scenarios, so you can use this as a reference in addition to our two other Entity Framework demos:

  • %PUBLIC%\Documents\DevExpress Demos 14.2\Components\eXpressApp Framework\EFDemoCodeFirst\
  • %PUBLIC%\Documents\DevExpress Demos 14.2\Components\eXpressApp Framework\EFDemoModelFirst\

Thursday, December 25, 2014

Looking for practical experiences with both DevExpress XPO & ADO.NET Entity Framework


----

You know that XAF supports both ORM libraries to almost the same extent, so there is no noticeable difference at the framework level (see 1, 2, 3) that should affect your choice in favor of a certain data access tool. There are, however, some differences between these ORMs in their functionality, usability, history and other factors which may indirectly affect your choice.



We do not provide comparisons of our products with competitors (mainly from an ethical point of view), but I think it would not hurt anyone if there was a list of proven opinions from users who had practical experience with both ORM tools. I already started collecting this list and among differences our users mentioned was, for instance:

Tuesday, December 23, 2014

What's New in XAF 14.2 Documentation

In addition to the new great features the version 14.2 introduced, there are also improvements to the learning materials that will allow you get the most of DevExpress products. 

The full list of What's New In Help for all products is waiting you here.
The XAF documentation changes are listed here. In particular, I wanted to focus on the restructured and improved Business Model Design section, which is, in my opinion, one of the most important things that contributes to overall understanding of the framework and its development process. 


My other favorite help topic is eXpressApp Framework > Concepts > UI Construction > List View Data Access Modes. Hopefully, even people familiar with the framework will find something helpful here. 


Wednesday, August 6, 2014

Forcing Boolean Property Editor to work for a string DB column

The world is not perfect and sometimes we have to deal with legacy data, which is not well organized. For instance, data which is binary by nature can be stored using predefined strings ("T"/"F" or "Y"/"N"):


Correcting data is not often possible, because this data can already be used by other information systems.
As you know, XAF automatically generates editors for data fields in the UI based on the field type in the ORM data model (learn more...), so in this particular case an inappropriate editor (text box) will be used if we leave the default mapping to a string column "as is" - a text box instead of a check box or drop down box with the Yes/No values. In this blog post I will show you several methods on how to work around this situation and have the correct editor in the UI while keeping the underlying data table schema and data unchanged.

Monday, June 30, 2014

Using a built-in lookup editor based on values from another table for editing simple property types

This is actually a variation of a solution I described in my recent A very interesting way to update and display a persistent property via a non-persistent one post, because it is again based on a non-persistent reference property filtered using the DataSourcePropertyAttribute along with a custom data source collection.
This non-persistent reference property is represented using the standard XAF's lookup PropertyEditors, which are quite convenient for providing a user with the capability to select a single value either from a database table or from an arbitrary data source. In one turn, by adding custom logic to the getter and setter of our non-persistent calculated property, we can update the stored persistent value, which does not need to be a reference to another persistent class (table), but to any type (e.g., string or integer). This may come in handy for legacy databases when you cannot really modify the schema to provide normal associations between tables.



Let's take a look at the actual code for this solution:

Wednesday, May 14, 2014

A very interesting way to update and display a persistent property via a non-persistent one

Scenario:

A customer wanted to extend the User class with additional property that would store the information about the startup View for this user when it launches the app. This is very similar to the StartupNavigationItem attribute, which is present for the NavigationItems node in the application model, but with the difference that application users should be able to modify this via the standard XAF CRUD forms.

How would you normally approach this?;-)

Possible solutions

At this time, I can think of at least three good options for accomplishing this task: two platform-dependent and one platform-agnostic, which I am going to detail later in this post. In all three cases we will extend our business class with a string property that would store this startup View information (its identifier) in the database.