Search This Blog

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.

4 comments:

  1. Hi, looks cool!
    Does this works with DomainComponent Interfaces?

    ReplyDelete
  2. Can you please show this sample in a class or controller

    ReplyDelete
    Replies
    1. @Boris: The code in a ViewController will actually be the same as above except for the fact that you should replace "objectSpaceB" with View.ObjectSpace or Application.CreateObjectSpace().
      Would you please describe your exact difficulties with this code snipped (what you tried and what did not work as expected)?

      Delete