Back to Devexpress

Direct SQL Queries

xpo-8914-query-and-shape-data-direct-sql-queries.md

latest10.3 KB
Original Source

Direct SQL Queries

  • Nov 12, 2020
  • 6 minutes to read

In XPO, you can execute direct SQL queries against a database and obtain query results as scalar values, result sets or object collections.

Executing SQL Statements

To execute a SQL statement that does not produce a result set, call the Session.ExecuteNonQuery method as shown below.

csharp
unitOfWork.ExecuteNonQuery("UPDATE [Northwind].[dbo].[Order Details]" +
    "SET [Discount] = 0.15 WHERE [UnitPrice] > 100");
vb
unitOfWork.ExecuteNonQuery("UPDATE [Northwind].[dbo].[Order Details]" &
    "SET [Discount] = 0.15 WHERE [UnitPrice] > 100")

To execute a SQL query and obtain a scalar value, call the Session.ExecuteScalar method.

csharp
public int GetEmployeeOrdersCount(int employeeId) {
    return (int)unitOfWork.ExecuteScalar(string.Format(
        "SELECT COUNT(*) FROM [Northwind].[dbo].[Orders] " +
        "WHERE [EmployeeID] = {0}", employeeId));        
}
vb
Public Function GetEmployeeOrdersCount(ByVal employeeId As Integer) As Integer
    Return CInt(Fix(unitOfWork.ExecuteScalar(
        String.Format("SELECT COUNT(*) FROM [Northwind].[dbo].[Orders] " &
            "WHERE [EmployeeID] = {0}", employeeId))))
End Function

To execute a SQL query and obtain a result set, call the Session.ExecuteQuery method.

csharp
using DevExpress.Xpo.DB;

// ...
static string queryString = "SELECT EmployeeID, (FirstName + ' ' " +
        "+ LastName) as Name, City, Country FROM " +
        "[Northwind].[dbo].[Employees]";

public SelectedData GetEmployeesSimpleData() {
    return unitOfWork.ExecuteQuery(queryString);
}
vb
Imports DevExpress.Xpo.DB

' ...
Private Shared queryString As String = "SELECT EmployeeID, (FirstName + ' ' " &
        "+ LastName) as Name, City, Country FROM " &
        "[Northwind].[dbo].[Employees]"

Public Function GetEmployeesSimpleData() As SelectedData
    Return unitOfWork.ExecuteQuery(queryString)
End Function

Visualizing Query Results

To visualize query results, you can:

To accomplish this, you need to provide a non-persistent class whose members specify a result set’s column structure. This class will be used to map result set columns to XPDataView columns or object properties.

In the following code example, the EmployeeSimple class corresponds to a result set returned via the GetEmployeesSimpleData function shown above. This class is used to populate an XPDataView with columns, and to obtain a collection of objects from a result set.

csharp
[NonPersistent]
public class EmployeeSimple : XPLiteObject {
    [Key]
    public int EmployeeID {
        get { return fEmployeeID; }
        set { SetPropertyValue(nameof(EmployeeID), ref fEmployeeID, value); }
    }
    int fEmployeeID;

    public string Name {
        get { return fName; }
        set { SetPropertyValue(nameof(Name), ref fName, value); }
    }
    string fName;

    public string City {
        get { return fCity; }
        set { SetPropertyValue(nameof(City), ref fCity, value); }
    }
    string fCity;

    public string Country {
        get { return fCountry; }
        set { SetPropertyValue(nameof(Country), ref fCountry, value); }
    }
    string fCountry;

    public EmployeeSimple(Session session) : base(session) { }
}

// ...

// Populate an XPDataView with columns based on the auxiliary class.
xpDataView1.PopulateProperties(unitOfWork.GetClassInfo<EmployeeSimple>());
// Load data from a query's result set to an XPDataView.
xpDataView1.LoadData(GetEmployeesSimpleData());

// Retrieve data from a query into a collection of objects.
ICollection<EmployeeSimple> collection = 
    unitOfWork.GetObjectsFromQuery<EmployeeSimple>(queryString);
vb
<NonPersistent()> _
Public Class EmployeeSimple
    Inherits XPLiteObject
    <Key> _
    Public Property EmployeeID() As Integer
        Get
            Return fEmployeeID
        End Get
        Set(ByVal value as Integer)
            SetPropertyValue(NameOf(EmployeeID), fEmployeeID, value)
        End Set
    End Property
    Private fEmployeeID As Integer

    Public Property Name() As String
        Get
            Return fName
        End Get
        Set(ByVal value as String)
            SetPropertyValue(NameOf(Name), fName, value)
        End Set
    End Property
    Private fName As String

    Public Property City() As String
        Get
            Return fCity
        End Get
        Set(ByVal value as String)
            SetPropertyValue(NameOf(City), fCity, value)
        End Set
    End Property
    Private fCity As String

    Public Property Country() As String
        Get
            Return fCountry
        End Get
        Set(ByVal value as String)
            SetPropertyValue(NameOf(Country), fCountry, value)
        End Set
    End Property
    Private fCountry As String

    Public Sub New(ByVal session As Session)
        MyBase.New(session)
    End Sub
End Class

' ...

' Populate an XPDataView with columns based on the auxiliary class.
xpDataView1.PopulateProperties(unitOfWork.GetClassInfo(Of EmployeeSimple)())
' Load data from a query's result set to an XPDataView.
xpDataView1.LoadData(GetEmployeesSimpleData())

' Retrieve data from a query into a collection of objects.
Dim collection As ICollection(Of EmployeeSimple) =
    unitOfWork.GetObjectsFromQuery(Of EmployeeSimple)(queryString)

If you do not want to show all class members in an XPDataView or if their order differs from the result set, then you can provide additional mapping information to obtain the proper columns in the correct order, as shown below.

csharp
static string queryOrderedString = "SELECT (FirstName + ' ' + LastName) " +
    "as Name, Country, EmployeeID FROM [Northwind].[dbo].[Employees]";

public SelectedData GetEmployeesSimpleDataOrdered()
{
    // Columns are mixed and the 'City' column is removed from the query.
    return unitOfWork1.ExecuteQuery(queryOrderedString);
}

// Define a mapping array that specifies the order of columns in a result set.
static LoadDataMemberOrderItem[] employeesLoadOrder = new LoadDataMemberOrderItem[] 
{
    new LoadDataMemberOrderItem(2, "EmployeeID"),
    new LoadDataMemberOrderItem(0, "Name"),
    new LoadDataMemberOrderItem(1, "Country")

};

// Populate an XPDataView with columns and load data using the specified mapping array.
xpDataView1.PopulatePropertiesOrdered(unitOfWork.GetClassInfo<EmployeeSimple>(), employeesLoadOrder);
xpDataView1.LoadOrderedData(employeesLoadOrder, GetEmployeesSimpleDataOrdered());

// Retrieve data from a result set into a collection of objects using the specified mapping array.
ICollection<EmployeeSimple> collection = 
    unitOfWork.GetObjectsFromQuery<EmployeeSimple>(employeesLoadOrder, queryOrderedString);
vb
Private Shared queryOrderedString As String = "SELECT (FirstName + ' ' + LastName) " &
    "as Name, Country, EmployeeID FROM [Northwind].[dbo].[Employees]"

Public Function GetEmployeesSimpleDataOrdered() As SelectedData
    ' Columns are mixed and the 'City' column is removed from the query.
    Return unitOfWork1.ExecuteQuery(queryOrderedString)
End Function

' Define a mapping array that specifies the order of columns in a result set.
Private Shared employeesLoadOrder() As LoadDataMemberOrderItem = 
{
    New LoadDataMemberOrderItem(2, "EmployeeID"),
    New LoadDataMemberOrderItem(0, "Name"),
    New LoadDataMemberOrderItem(1, "Country")
}

' Populate an XPDataView with columns and load data using the specified mapping array.
xpDataView1.PopulatePropertiesOrdered(unitOfWork.GetClassInfo(Of EmployeeSimple)(), employeesLoadOrder)
xpDataView1.LoadOrderedData(employeesLoadOrder, GetEmployeesSimpleDataOrdered())

' Retrieve data from a result set into a collection of objects using the specified mapping array.
Dim collection As ICollection(Of EmployeeSimple) = 
    unitOfWork.GetObjectsFromQuery(Of EmployeeSimple)(employeesLoadOrder, queryOrderedString)

The examples above demonstrate a strongly-typed approach, where XPDataView automatically retrieves properties from a non-persistent classe. XPDataView also can work in untyped mode. To use XPDataView without non-persistent classes, populate the XPDataView.Properties collection:

csharp
Session session = new Session();
SelectedData data = session.ExecuteSproc("sprocName", parameters);
IList<string> propertyNames = new List<string>() { "ProductName", "Total" };
IList<Type> propertyTypes = new List<Type>() { typeof(string), typeof(int) };
XPDataView dataView = new XPDataView(session.Dictionary, propertyNames, propertyTypes);
dataView.LoadData(data);
vb
Dim session As New Session()
Dim data As SelectedData = session.ExecuteSproc("sprocName", parameters)
Dim propertyNames As IList(Of String) = New List(Of String)() From {"ProductName", "Total"}
Dim propertyTypes As IList(Of Type) = New List(Of Type)() From {GetType(String), GetType(Integer)}
Dim dataView As New XPDataView(session.Dictionary, propertyNames, propertyTypes)
dataView.LoadData(data)

See Also

How to: Access Data in SQL Query Results