Today we have a closer look at using LINQ and anonymous types and it's pros and cons.

Consider the case where we want to obtain a subset of data instead of an entire persistent instance. For example, if we want to obtain the contact details of all Customers based in London we would use the following query

var query = from c in scope.Extent<Customer>()
                  
where c.City.Equals("London")
                  
select new { c.City, c.Address, c.ContactName };
 

Notice the last line in the above query - select new { c.City, c.Address, c.ContactName }
This line creates an anonymous type. Behind the scenes, at compile time, a very simple class is generated automatically. In this case, three properties, City, Address and ContactName, are added to the class.

The result of the query can be processed further using the var keyword as follows -

foreach(var contact in query)
   
Console.WriteLine(contact);
 
There are a couple of problems with the above approach -
  1. Since var cannot be used in the parameter list or the return type of a method, anonymous types can be used only within the scope of the current method.There is usually no way to pass it to another method or broaden it's scope.
  2. You could get over this by declaring a type that contains members to hold the result and use that instead of the anonymous type. We can do this as follows -
public class CustomerContact
{
   
public string City { get; set; }
   
public string Address { get; set; }
   
public string ContactName { get; set; }
}
 
and the query would now be
var query = from c in scope.Extent<Customer>() 
                  
where c.City.Equals("London")                  
                   select new CustomerContact { City = c.City, Address = c.Address, ContactName = c.ContactName };
 
But what if you need additional data? You would then need to modify the query and also the temporary type declaration accordingly. Definitely tedious!
You might want to use this approach thinking that it is more efficient to query for only the required columns rather than the entire instance, but this is not necessarily the case.
 
To explain this further, here is the actual SQL query that is executed for the LINQ query mentioned above.
SELECT [City] AS COL1, [Address] AS COL2, [ContactName] AS COL3 FROM [Customers] WHERE [City] = 'London'
 

To avoid the overhead of using anonymous types and to achieve the same minimal query, you could use the Telerik OpenAccess ORM FetchPlan API. All you need to do is specify the FetchFieldAttribute, with a fetch group name, for the fields you want to retrieve and use that FetchGroup instead of the ‘Default Fetch Group’. So your code would now be something like this

  • Add the fields to the FetchGroup
 public partial class Customer 
   
{
       
private string customerID; // pk 

       
[Telerik.OpenAccess.FetchField("ContactDetails")]
       
private string address;

       
[Telerik.OpenAccess.FetchField("ContactDetails")]
       
private string city;

       
private string companyName;

       
[Telerik.OpenAccess.FetchField("ContactDetails")]
       
private string contactName;

       
private string contactTitle; 
        ……..
 
        ……..
}
 
  • Instruct OpenAccess to use this FetchGroup
scope.FetchPlan.Clear();
scope.FetchPlan.Add("ContactDetails"); //where 'ContactDetails' is the fetch group name that you specify at the FetchFieldAttribute 

var query = from c in scope.Extent<Customer>()
                  
where c.City.Equals("London")
                  
select c;

This would generate the following SQL query

SELECT [CustomerID] AS COL1, [Address] AS COL2,[City] AS COL3, [ContactName] AS COL4 FROM [Customers] WHERE [City] = 'London'

 

The only difference to the anonymous type query is the additional CustomerID column that is required for the change tracking features. So using FetchPlans over anonymous types requires you to write lesser code which can be very easily extended and you also retain the Telerik OpenAccess ORM flexibility like change tracking, for the retrieved instances.

Hope this tip was encouraging and stay tuned for more.


Comments

Comments are disabled in preview mode.