Skip to main content
All docs
V23.2
.NET 6.0+

XAF0018: Avoid creating a new Session/UnitOfWork with parameterless constructors in XPO-based projects

  • 3 minutes to read

Severity: Error

Do not create a new Session/UnitOfWork with parameterless constructors in XPO-based projects. In business class code, use a Session accessible through your business class’s BaseObject.Session property. To work with data in Controllers, use IObjectSpace.

When you create a new Session or UnitOfWork with a parameterless constructor (or pass XpoDefault.DataLayer as a parameter) in XAF apps, no data is queried from the database because this session is not bound to the application database. Your code may work in basic scenarios only when you initialize XpoDefault.DataLayer with the same XAF application data layer and have a direct database connection with XPObjectSpaceProvider. If you have not initialized XpoDefault.DataLayer properly, your code will fail when you use SecuredObjectSpaceProvider, MiddleTierServerObjectSpaceProvider, or a customized data layer.

Examples

Invalid Code

using DevExpress.Persistent.Base; 
using DevExpress.Persistent.BaseImpl; 
using DevExpress.Xpo; 
using DevExpress.ExpressApp;

namespace MySolution.Module.BusinessObjects{ 
    public class TestClass : BaseObject {
        public void TestMethod(){
            // Do not create a new Session with a parameterless constructor to connect to the same XAF application database
            Session newSession = new Session(); //!!! OR new Session(XpoDefault.DataLayer);
            var customers = new XPCollection<Customer>(newSession);
        }
    }
}
namespace MySolution.Module.Controllers {
    public class TestController : ViewController {
        public void TestMethod(){
            // Do not create a new Session with a parameterless constructor to connect to the same XAF application database
            var newSession = new UnitOfWork(); //!!! OR new UnitOfWork(XpoDefault.DataLayer);
            var newObject = new TestClass(newSession);
            newSession.ExecuteNonQuery("SELECT 1");
        }
    }
}

Valid Code

using DevExpress.Persistent.Base; 
using DevExpress.Persistent.BaseImpl; 
using DevExpress.Xpo; 
using DevExpress.ExpressApp;

namespace MySolution.Module.BusinessObjects {
    // This code meets the requirements.
    // It uses a Session retrieved from a class' Session property
    public class TestClass : BaseObject {
        public void TestMethod(){
            var customers = new XPCollection<Customer>(Session);
        }
    }
}
namespace MySolution.Module.Controllers {
    // This code meets the requirements.
    public class TestController : ViewController {
        public void TestMethod(IObjectSpace objectSpace){
            // Use the IObjectSpace API directly.
            var newObject = objectSpace.CreateObject<TestClass>();

            // Use the XPObjectSpace.Session property if IObjectSpace has no equivalents of the Session API.
            var uow = ((XPObjectSpace)objectSpace).Session;
            uow.ExecuteNonQuery("SELECT 1");
        }
    }
}

How To Fix

In business class code, use a Session accessible through your business class’s BaseObject.Session property.

To work with data in XAF Controllers, use IObjectSpace. Refer to the following topic for more information: Object Space. If you want to access the Session API, for which IObjectSpace has no equivalents (for instance, ExecuteNonQuery), use the XPObjectSpace.Session property instead (var uow = ((XPObjectSpace)yourObjectSpace).Session;).

Outside of XAF Controllers and business classes (for instance, if you created a Session to connect to the same XAF application database in a non-XAF UI service to read XAF business object data), consider using IObjectSpace as described at Access XAF Application Data in a non-XAF Application. If you have a helper class consumed in XAF Controllers or non-XAF UI service, consider passing IObjectSpace from the consumer context as method parameters:

public static HelperClass {
    public void HelperClassMethod(IObjectSpace objectSpace) { /*...*/}
}