Search This Blog

Showing posts with label XPO. Show all posts
Showing posts with label XPO. Show all posts

Tuesday, April 3, 2018

Old entries in the XPObjectType table - YOUR FEEDBACK IS NEEDED!


I am reviewing the priority of a quite dated SC item on the subject and wanted to ask the community for help. The problem may occur when old business class libraries exist in the application folder. By default, XPO tries to load them by the XPObjectType info along with the new versions. This may lead to a conflict at runtime or startup performance degradation. In the latter case, assembly type resolution may come at a cost (see the point 3.5 under How to measure and improve the application's performance).

Why are we hesitating to remove old XPObjectType entries by default?
1. Removing old XPObjectType records affects other apps accessing this database and is serious. Outdated service table records may relate to business class records too (inheritance mapping is in use very often). So, deleting them will lead to foreign key constraint violation. Creating a sophisticated generic solution for this is not easy task.

Monday, March 26, 2018

Integrating UnitOfWork and XPObjectSpace descendants into an XAF app


We've made some code changes for v17.2.6+ as well as created two articles for advanced XAF developers who may need the subject for some low-level tuning:





Sub-classing is itself easy.  The most interesting part comes for the two popular security configurations: the Integrated  mode and the Middle-Tier Application Server. Thankfully, this is rarely required for complex or specific scenarios only.  Here are several customer tickets for your reference:

    How to map a property to a calculated database column (implement a read-only persistent property)
    xpo and sql server identity fields
    Using inherited UnitOfWork object
    XAF: Create CreateCustomObjectSpaceProvider with parameters from login window
    SecurityStrategyComplex: How to modify objects/properties in code when the user does not have the permission?

To learn more about low-level options to control how your application saves data and where, check out the How to customize the underlying database provider options and data access behavior in XAF.

Your feedback is needed!
Finally, I am just curious: if you search your entire solution in Visual Studio (Control+Shift+F) for any of the ": UnitOfWork", ": XPObjectSpace", ": XPObjectSpaceProvider" strings or their VB.NET equivalents (e.g., Inherits UnitOfWork), how many occurrences  would you have and for what? Please let me know in the comments!

FreeImages.com/Terry Eaton

Monday, November 27, 2017

Welcome the DataStoreCreated event in the ConnectionDataStoreProvider and ConnectionStringDataStoreProvider classes

This is rather a minor improvement, but I bet it will save code lines for some advanced XAFers who touch the internals of the XPO data layer created by XAF for various low-level database-specific customization like setting connection timeouts, changing default schemas, enabling and customizing caching, service end-points, etc. Check out this updated article for some example code showing the new approach in action.
The DataStoreCreated  event is available in XAF v17.2+. Its event arguments (DataStoreCreatedEventArgs) expose the DataStore and Destination parameters that provide access to the current data store and its type (SchemaChecking,  Updating or Working).

Frankly speaking, this is quite low-level and rarely needed stuff, so we have not yet have it covered in the online docs, only in KBs. So, please refer to my 
How to customize the underlying database provider options and data access behavior in XAF article to learn more about it. Should you have any questions or additional usability suggestions, please let me know.

FreeImages/Chett Cole

Wednesday, June 7, 2017

XPQuery changes regarding non-persistent properties in v17.1

In version 17.1, we have improved error detection in XPQuery when non-persistent properties are used in it. Previously, such queries didn't work (either failed with various exceptions or worked incorrectly) and thus there were hidden errors in your programs. Now, we throw an exception that describes which non-persistent properties are used in XPQuery to help diagnosing these errors. If such properties are used intentionally, consider implementing them using PersistentAliasAttribute or adding the ToList method call to explicitly process these properties on the client side.

Refer to the https://www.devexpress.com/kb=T523335 KB Article for examples and more details.

FreeImages.Com/sanja gjenero

Tuesday, March 14, 2017

XAF app performance: Reducing the number of simultaneous database connections



Multiple simultaneously opened connections consume your database server memory and thus, have negative impact on your application performance. To diagnose this situation, you can use the following SQL script:

SELECT 
    DB_NAME(dbid) as DBName, 
    COUNT(dbid) as NumberOfConnections,
    loginame as LoginName
FROM
    sys.sysprocesses
WHERE 
    dbid > 0
GROUP BY 
    dbid, loginame

Thankfully, there is a couple of tricks to optimize your existing apps in production (they are already applied out of the box in new projects).


Monday, December 14, 2015

XPO ORM Data Model Designer and Wizard FAQ

My fellow colleague Michael has recently written an article based on the most popular support calls regarding the visual designer that XPO ships with, for editing visual data models. Some things may already be known to you, but others are worth repeating and I hope you will find this short doc helpful:



Thursday, July 23, 2015

Making the AuditTrail functionality operate correctly with several XPObjectSpaceProviders when storing data in separate databases (15.1.6)

I wanted to inform the community of a solution we have just finished testing for the next XAF version in response to the following customer's business scenario:

"i followed this instruction to work with two databases in one application. so far so good. 
i also managed to include the security module and get it working, but now i don't know how to use the "audit trail" module! it doesn't seem to matter in which project i include it, but it will not save anything to the database."


As you probably know, XAF supports connecting to several databases and even using both Entity Framework (EF) and eXpress Persistent Objects (XPO) at the same time (examples: onetwothree), although it is not the primary scenario, to be honest. 

In short, if you were in need of such a configuration and wanted to have AuditTrail capabilities, it would "just work" starting with v15.1.6. If you feel confident to check technical details on this, see my description in the T263982 - AuditTrail - Ensure support for scenarios with several XPObjectSpaceProviders ticket.
By providing support for this module, we continue working in the direction we took in the past, which I also discussed in the past blog. As always, our team is looking forward to hearing your feedback in this regard.

Friday, June 26, 2015

Creating associations between XPO data models in code using the XafTypesInfo API



Prerequisites:
See my About XAF Types Info Subsystem... blog post before reading.

What's New in this regard?
Just wanted to inform you guys that starting with v15.1.4, you can use the solution described in the eXpressApp Framework > Concepts > Business Model Design > Types Info Subsystem > Customize Business Object's Metadata > Create Associations in Code article for that purpose:

The following snippet illustrates how to declare an association between two class' properties when you have no access to these classes code and cannot apply the AssociationAttribute directly.

C#
ITypeInfo typeInfo1 = typesInfo.FindTypeInfo(typeof(DomainObject1));
ITypeInfo typeInfo2 = typesInfo.FindTypeInfo(typeof(DomainObject2));
IMemberInfo memberInfo1 = typeInfo1.FindMember("Object2");
IMemberInfo memberInfo2 = typeInfo2.FindMember("Object1s");
if(memberInfo1 == null) {
    memberInfo1 = typeInfo1.CreateMember("Object2"
        typeof(DomainObject2)
    );
    memberInfo1.AddAttribute(
        new DevExpress.Xpo.AssociationAttribute("A"
        typeof(DomainObject2)), true
    );
}
if(memberInfo2 == null) {
    memberInfo2 = typeInfo2.CreateMember("Object1s"
        typeof(XPCollection<DomainObject1>)
    );
    memberInfo2.AddAttribute(
        new DevExpress.Xpo.AssociationAttribute("A"
        typeof(DomainObject1)), true
    );
    memberInfo2.AddAttribute(
        new DevExpress.Xpo.AggregatedAttribute(), true
    );
}
((XafMemberInfo)memberInfo1).Refresh();
((XafMemberInfo)memberInfo2).Refresh();

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. 

Thursday, March 12, 2015

How to map ORM data model to another schema, e.g. other than the default "dbo" in MS SQL Server?

I just wanted to bring your attention to the recent update of one of the articles in our support knowledge, which is devoted to advanced data layer customizations - telling XAF business objects to use a different owner schema in the database.



Here we go:

Tuesday, March 3, 2015

Usability improvements for new XAF apps using XPO for data access

I would like to inform you that the next v14.2.6 update of XAF will contain two minor improvements that will help you accomplish two common tasks more easily or help you have less problems with them. Both will affect only new XAF projects created using the Solution Wizard (existing XAF projects will not be touched to avoid collisions). Also, both things were implemented based on the feedback from our users and I hope will be welcomed by them as less work to be done is left for you now.

Here I will shortly outline solution details while you can see the full information by the links below:

T191131: DevExpress.Persistent.BaseImpl - Avoid problems caused by the fact that a new BaseObject record has an empty key value until it is saved

In XAF Solutions created via the Solution Wizard, the BaseObject.OidInitializationMode static property is now set to AfterConstruction using the following code line added to the Module.cs file:
[C#]
BaseObject.OidInitializationMode = OidInitializationMode.AfterConstruction;
We do not modify the default value in the BaseObject class implementation to avoid the behavior change in existing applications.

S173546: Usability - Remove the necessity to manually call the CalculatedPersistentAliasHelper.CustomizeTypesInfo method from custom code when CalculatedPersistentAliasAttribute is used

Now, in XPO-based XAF solutions created with the Solution Wizard the following line is added to the overridden CustomizeTypesInfo method in the Module.cs file:
[C#]
CalculatedPersistentAliasHelper.CustomizeTypesInfo(typesInfo);
You can remove this line if you do not need to use CalculatedPersistentAliasAttribute.

As always, I look forward to your feedback in comments. If you know about other things that may greatly improve your experience as an XAF developer, do not hesitate to let me know.

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:

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.

Saturday, July 19, 2014

How to customize the underlying database provider options and data access behavior in XAF


I just wanted to repost my recent update to the corresponding article, because this information can interest some advanced XAF users.

IMPORTANT NOTE

This article describes some advanced customization techniques and low-level entities of the framework with regard to data access, which may be required in complex scenarios only.
So, if you just want to change the connection string, e.g. to use the Oracle instead of the Microsoft SQL Server database, then you would better refer to the Connect an XAF Application to a Database Provider article and documentation on your database provider instead. The XAF integration of supported ORM libraries is also described in the Business Model Design section of the framework's documentation.

Introducing IObjectSpaceProvider and IObjectSpace

XAF accesses data from a data store through special abstractions called - IObjectSpaceProvider and IObjectSpace.
The IObjectSpace is an abstraction above the ORM-specific database context (e.g., the DBContext used in Entity Framework or the Session in XPO) allowing you to query or modify data.
The IObjectSpaceProvider is a provider/creator of IObjectSpace entities, which also manages which business types these IObjectSpace are supposed to work with, how to set up the underlying connection to the database, create and update it and other low level data access options.



An XafApplication can use one or several IObjectSpaceProvider objects at the same time, and you can access this information through the XafApplication.ObjectSpaceProvder or XafApplication.ObjectSpaceProviders properties. Check out these help links to learn more on how to plug in custom IObjectSpaceProvider objects a well.

There are several built-in implementations of the IObjectSpaceProvider and IObjectSpace interfaces in our framework, which are usually specific to a target ORM (Entity Framework or XPO). I suggest you check out the source code of the default framework classes to better understand the role of the IObjectSpaceProvider:
...\DevExpress.ExpressApp.Xpo\XPObjectSpaceProvider.cs
...\DevExpress.ExpressApp.EF\EFObjectSpaceProvider.cs 

Wednesday, February 12, 2014

My Top 10 favorite DevExpress CodeRush features for .NET development in Visual Studio

http://habrahabr.ru/company/devexpress/blog/211805/

This is my recent post on HabraHabr (a sort of TechCrunch in Russia) about my favorite CodeRush functions. If you do not understand Russian, try using Google Translate, Google Chrome or just watch the videos from this post.

Tuesday, October 1, 2013

How to generate a sequential and user-friendly identifier field within a business class

I have just created a new Code Example that demonstrates a very simple solution for the subject:

"Orders, articles or other business entities often require that you have user-friendly Id or Code fields that end-users can memorize and use during phone conversations. They are usually sequential, but some gaps can be allowed as well (e.g., when an order is deleted). Refer to this StackOverFlow thread for more information on this common scenario, and a possible implementation."

Check out http://www.devexpress.com/example=E4904 for a step-by-step instruction on how to implement this. 



It is based on the DistributedIdGeneratorHelper class from the DevExpress.Persistent.BaseImpl library (I know that many of you have already been using it for years).
I hope you will like this simple, but quite powerful solution, which can be considered as an alternative to the How to generate and assign a sequential number for a business object within a database transaction, while being a part of a successful saving process (XAF) example. 

Monday, September 9, 2013

DevExpress.Xpo.v13.1.Extensions is now available for WCF Data Services 5.6

I forgot to inform you of the newly added support for WCF Data Services 5.6 in XPO, which you may be interested in (download a patch with this support included) if you are using our OData extensions that allow you to expose your XPO data model and work with it via OData protocol (check my previous blogs to learn more on this).

Microsoft is baking and selling new WCF Data Services versions like hot cookies lately, so we need to follow and provide separate versions of our OData extensions quite often for our customers:



Friday, April 19, 2013

The capability to not mark a persistent object as modified for saving if only its non-persistent properties were changed

I am not sure if this will be helpful for many XPO customers, but there is definitely a number of scenarios where you may welcome the implemented behavior. Refer to the tickets below to learn more.

http://www.devexpress.com/Support/Center/p/Q489119.aspx - implemented in 13.1 where you can use the new XpoDefault.IsObjectModifiedOnNonPersistentPropertyChange and Session.IsObjectModifiedOnNonPersistentPropertyChange properties.

http://www.devexpress.com/Support/Center/Question/Details/Q408356 
http://www.devexpress.com/Support/Center/Issues/ViewIssue.aspx?issueid=S34863 - requested in the past by other customers.

Take special note that in the current version it is already possible to avoid change notifications for non-persistent properties by not using the

OnChanged or SetPropertyValue methods in setters of your non-persistent properties.

Thursday, April 11, 2013

Recent XPO improvements to the visual designer and OData

Just a small update to to ensure that you have not missed the subject and added it to your development arsenal:

  • S171017 - ORM Data Model Wizard - Make it possible to apply custom attributes for association properties (coming in 13.1)
  • S170003 - ORM Data Model Wizard - Provide the capability to copy properties between persistent objects (coming in 12.2.8)
  • S170964 - XpoDataServiceV3 - Provide a virtual method to create a custom Session (coming in 12.2.8)

    How to leverage the latter functionality is described at Exposing Domain Components (DC) via OData for mobile apps
  • As you probably know, the next maintenance update (12.2.8) is on its way. Once it is officially out, do not forget to check out its change log that contains information about both fixed issues and implemented suggestions, as well as updates to our documentation.

    Wednesday, April 3, 2013

    Exposing Domain Components (DC) via OData for mobile apps

    As you probably know, it is possible to use DC in non-XAF applications as described at eXpressApp Framework > Task-Based Help > How to: Use Domain Components in non-XAF Applications

    So, I will use a similar approach in my XPO-based OData Service project (you can learn more on how to create it via the wizard here). Once I created the service, I will have to modify my XpoDataServiceV3 descendant as shown below:

    [JSONPSupportBehavior]
    public class DCDataService : XpoDataServiceV3 {
        static XPObjectSpaceProvider objectSpaceProvider = null;
        static readonly DataService1Context serviceContext =  new DataService1Context("XpoContext",
            "DevExpress.ExpressApp.DC.GeneratedClasses", CreateDataLayer()
        );
        protected override UnitOfWork GetSessionCore(IObjectLayer objectLayer) {
            if (objectSpaceProvider != null) {
                XPObjectSpace os = (XPObjectSpace)objectSpaceProvider.CreateObjectSpace();
                return (UnitOfWork)os.Session;
            }
            return base.GetSessionCore(objectLayer);
        }
        static IDataLayer CreateDataLayer() {
            XpoTypesInfoHelper.ForceInitialize();
            var typesInfo = XpoTypesInfoHelper.GetTypesInfo();
            var xpoTypeInfoSource = XpoTypesInfoHelper.GetXpoTypeInfoSource();

            typesInfo.RegisterEntity("Survey" typeof(ISurvey));
            typesInfo.GenerateEntities();         

            var connectionString = "Integrated Security=SSPI;Pooling=false;Data Source=(local);Initial Catalog=TestDb";
            var dataStoreProvider = new ConnectionStringDataStoreProvider(connectionString);
            objectSpaceProvider = new XPObjectSpaceProvider(dataStoreProvider, typesInfo, xpoTypeInfoSource, true);
            objectSpaceProvider.CreateObjectSpace(); // Force the objectSpaceProvider.DataLayer property initialization.
            XpoDefault.DataLayer = objectSpaceProvider.DataLayer;
            DevExpress.Xpo.XpoDefault.Session = null;
            return XpoDefault.DataLayer;
        }
    }

    Here I would like to focus on three things:
    1. I initialized the static serviceContext variable and provide the namespace of our auto-generated DC entities as the second parameter: "DevExpress.ExpressApp.DC.GeneratedClasses". It is important to avoid dealing with long-named entities like "DevExpress_ExpressApp_DC_GeneratedClasses_Survey" in our consumer applications.

    2. I initialized the data layer that is used by my XpoContext descendant via the static CreateDataLayer method. There I used some XAF magic, which is required for DC, because domain logic methods accept the parameters of the IObjectSpace type. If I did not use DC, then I would not use the XAF classes in my data service and rather go using pure XPO stuff.

    3. I overrode the GetSessionCore to use the Session created by the XAF's ObjectSpace, again for the correct work of domain logic methods. Take special note that this virtual method is available in version 12.2.8+ only (thanks to our XPO guys for implementing my request so quickly;-)). If you want to test it right away, I have included the latest version of the DevExpress.Xpo.v12.2.Extensions assembly into the demo project I posted here.

    Finally, let me demonstrate why I created the OData service in the first place. Of course, I needed it for my mobile DXTREME application:


    View on screencast.com »


    UPDATE:
    Originally when experimenting with this DC-based service I tried to reference the DcAssembly.dll into my data service project. This cache assembly is automatically generated by XAF when running the application with no debugger attached. So, to get it, I simply ran my XAF WinForms application, which used the same data model, and then copied the generated assembly from the Release/Bin folder into my data service project. Since this assembly contains regular persistent classes instead of DC interfaces (remember my recent talk about different types?), I hoped that this way it might be easier for you to understand and work with. Unfortunately, I had to stop using this undocumented approach later, because it required additional configuration from the application for the correct operation of the DC-based functionality: normally, when XAF loads this assembly internally it also calls the private void ProcessGeneratedAssembly(Assembly generatedAssembly) method of the XpoTypeInfoSource class. Another reason is that with the DcAssembly.dll approach it would also be more difficult to deploy and maintain the app due to the overhead on generating and copying the assembly...