Skip to main content
All docs
V23.2

Create a New Object

  • 5 minutes to read

Useful API

You can use following Object Space methods to create a new object:

IObjectSpace.CreateObject
Creates an object of the specified type.
IObjectSpace.CreateObject<ObjectType>
Creates an object of the type designated by the specified generic type parameter.
IObjectSpace.IsNewObject
Indicates whether a specified object has been created but has not been saved to the database.
IObjectSpace.CommitChanges
Saves all the changes made to the persistent objects belonging to the current Object Space to the database.

In a Controller (the ORM-Independent Technique)

  1. Create a new View Controller in a Module project (for example, in MySolution.Module).
  2. Use the ViewController.ObjectSpace property to access an Object Space for data-aware operations.
  3. Use the Object Space’s methods to create a new object.
  4. Call the CommitChanges() method to save changes.

Example 1

The following Controller contains the AddTask Action that creates a new Task object:

File: MySolution.Module\Controllers\TaskViewController.cs(.vb).

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Actions;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
// ...
public class TaskViewController : ObjectViewController<ListView, Task> {
    public TaskViewController() {
        SimpleAction addTaskAction = new SimpleAction(this, "AddTask", PredefinedCategory.Edit);
        addTaskAction.Execute += AddTaskAction_Execute;
    }
    private void AddTaskAction_Execute(object sender, SimpleActionExecuteEventArgs e) {
        Task task = ObjectSpace.CreateObject<Task>();
        task.Subject = "Demo Task";
        View.CollectionSource.Add(task);
        ObjectSpace.CommitChanges();
        View.Refresh();
    }
}

Example 2

The following Controller contains the AddTask Action that adds a new Task object to the Employee‘s Tasks collection. This Controller activates for the Employee Detail View and accesses the nested Tasks List View as described in the following topic: How to: Access Nested List View or Master Detail View Environment (ASP.NET Core Blazor and Windows Forms).

File: MySolution.Module\Controllers\EmployeeViewController.cs(.vb).

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Actions;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.ExpressApp.Editors;
// ...
public class EmployeeViewController : ObjectViewController<DetailView, Employee> {
    public EmployeeViewController() {
        SimpleAction addTaskAction = new SimpleAction(this, "AddTask", PredefinedCategory.Edit);
        addTaskAction.Execute += AddTaskAction_Execute;
    }
    private void AddTaskAction_Execute(object sender, SimpleActionExecuteEventArgs e) {
        ListPropertyEditor listPropertyEditor = View.FindItem(nameof(Employee.Tasks)) as ListPropertyEditor;
        IObjectSpace os = listPropertyEditor.ListView.ObjectSpace;
        Task task = os.CreateObject<Task>();
        task.Subject = "Demo Task";
        listPropertyEditor.ListView.CollectionSource.Add(task);
        os.CommitChanges();
        listPropertyEditor.ListView.Refresh();
    }
}

In an XPO Business Class

In an XPO business class, use the required business class constructor to create a new object and pass the current object’s Session as the constructor parameter. You can do this in the overridden AfterConstruction method.

The following code snippet demonstrates how to initialize Employee‘s Address1 and Manager reference properties with new and existing objects:

File: MySolution.Module\BusinessObjects\Contact.cs(.vb)

using DevExpress.Data.Filtering;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Xpo;
// ...
public class Employee : Person {
    //...
    public override void AfterConstruction() {
        base.AfterConstruction();
        Address1 = new Address(Session);
        Address1.Country = Session.FindObject<Country>(CriteriaOperator.Parse("Name = 'USA'"));
        if(Address1.Country == null) {
            Address1.Country = new Country(Session);
            Address1.Country.Name = "USA";
        }
        Manager = Session.FindObject<Employee>(CriteriaOperator.Parse(
            "FirstName = 'John' && LastName = 'Doe'"));
    }
}

In a EF Core Business Class

  1. EF Core persistent classes implement the IObjectSpaceLink interface at runtime.
  2. Cast a persistent object to the IObjectSpaceLink interface and get the ObjectSpace property value.
  3. Use the ObjectSpace methods to create a new object.

The following code snippet demonstrates how to initialize the Address1 reference property with a new or existing object:

File: MySolution.Module\BusinessObjects\Employee.cs

using DevExpress.Data.Filtering;
using DevExpress.ExpressApp;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl.EF;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YourSolutionName.Module.BusinessObjects;
[DefaultClassOptions]
public class Employee : IXafEntityObject {
    [Key]
    public virtual Guid ID { get; set; }

    public virtual string Manager { get; set; }
    public void OnCreated() {
        // ...
        var address = ObjectSpace.FindObject<Address>(CriteriaOperator.FromLambda<Address>(a => a.Country == "USA"));
        if(address == null) {
            address = ObjectSpace.CreateObject<Address>();
            address.Country = "USA";
        }
        Address1 = address;
    }
    public virtual Address Address1 { get; set; }
    public void OnLoaded() { }
    public void OnSaving() { }
    public IObjectSpace ObjectSpace {
        get {
            return ((IObjectSpaceLink)this).ObjectSpace;
        }
    }
}
[DefaultClassOptions]
[DefaultProperty(nameof(Country))]
public class Address : BaseObject {
    public virtual string Country { get; set; }
    // ...
}
// Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.

Alternatively, you can inherit your class from the DevExpress.Persistent.BaseImpl.EF.BaseObject class as follows:

using DevExpress.Data.Filtering;
using DevExpress.ExpressApp;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl.EF;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YourSolutionName.Module.BusinessObjects;
[DefaultClassOptions]
public class Employee : BaseObject {
    public virtual string Manager { get; set; }
    public override void OnCreated() {
        // ...
        var address = ObjectSpace.FindObject<Address>(CriteriaOperator.FromLambda<Address>(a => a.Country == "USA"));
        if(address == null) {
            address = ObjectSpace.CreateObject<Address>();
            address.Country = "USA";
        }
        Address1 = address;
    }
    public virtual Address Address1 { get; set; }

}
[DefaultClassOptions]
[DefaultProperty(nameof(Country))]
public class Address : BaseObject {
    public virtual string Country { get; set; }
    // ...
}


// Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.