Ask a questionAsk a question
 

AnswerLINQ to Entities with EDM Inheritance

  • Wednesday, October 10, 2007 2:27 PMZoran Vujic Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Here is model fragment:

     

    // This class is root-EntitySet
    public class InvolvedParty
    {
        public sting ObjectId;
    }

    public class Organization : InvolvedParty;

    public class OrganizationUnit : InvolvedParty
    {
        public Organization Parent;
    }

     

    I want to retrieve all OrganizationUnits for given Organization (defined by its ObjectId - organizationId). I've made query:

     

    var query = from ip in context.InvolvedParty
                where ip is OrganizationUnit
                //&& ((OrganizationUnit)ip).Parent.ObjectId == organizationId
                select ip;

     

    I've included commented line to narrow search, but that line throws exception when query is loaded:

     

    System.NotSupportedException: Unable to cast type 'InvolvedParty' to 'OrganizationUnit'. LINQ to Entities supports only casts of entity data model primitive types.

     

    I could do additional filtering in two foreach loops, but it is done on client:

     

    // 1st loop to load entities
    List<OrganizationUnit> tempList = new List<OrganizationUnit>();
    foreach (InvolvedPartyRepositoryIDModel.InvolvedParty item in query)
    {
         tempList.Add((OrganizationUnit)item);
    }

     

    // 2nd loop to load navigation property
    foreach (InvolvedPartyRepositoryIDModel.OrganizationUnit item in tempList)
    {
        item.ParentReference.Load();
                       
        if (item.Parent != null &&
           item.Parent.ObjectId == organizationId)
        {
            // ...           
        }
    }


    Is there any way to make optimized LINQ query that will do filtering on database server?

     

Answers

  • Wednesday, October 10, 2007 7:25 PMDaniel Simmons - MSFTOwnerUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    There's probably a more linq-centric way to do this (honestly I tend to use eSQL and the ObjectQuery<T> builder methods rather than LINQ), but the way I would do it is using a builder method on the initial source of your query to apply your initial filter.  That way you don't have to cast in the where clause because the only things returned are already guaranteed to be of the correct type.  So your query would look like this:

     

    var query = from ou in context.InvolvedParty.OfType<OrganizationUnit>

    where ou.Parent.ObjectId == organizationId

    select ou;

     

    - Danny
  • Thursday, October 11, 2007 4:33 PMDiego B VegaMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    To add to Danny's answer, here is something one of our developers pointed out (thanks Colin):

     

    Cast operations are reserved for database ‘convert’ operations. ‘Is’, ‘As’ and ‘OfType<T>’ on the other hand are available for nominal type operations. 

     

    Then, a more "linquesque" way to do this would be:

     

    var query = from ip in context.InvolvedParty
                where ip is OrganizationUnit
                && (ip as OrganizationUnit).Parent.ObjectId == organizationId
                select ip;

     

    Please, tell me if it works for you.

     

    Regarding your other question, I think the more general answer is (as Danny shows) that it is a matter of taste. A more technical criteria would be: If don't know beforehand what IQueryable implementation your queries will be targeting, you will probably want to stick to LINQ. Otherwise you can freely mix and match.

     

    - Diego

     

    Note: OfType<T> should actually work with any IQueryable implementation. It only makes your query look a little more bumpy Smile

All Replies

  • Wednesday, October 10, 2007 7:25 PMDaniel Simmons - MSFTOwnerUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    There's probably a more linq-centric way to do this (honestly I tend to use eSQL and the ObjectQuery<T> builder methods rather than LINQ), but the way I would do it is using a builder method on the initial source of your query to apply your initial filter.  That way you don't have to cast in the where clause because the only things returned are already guaranteed to be of the correct type.  So your query would look like this:

     

    var query = from ou in context.InvolvedParty.OfType<OrganizationUnit>

    where ou.Parent.ObjectId == organizationId

    select ou;

     

    - Danny
  • Thursday, October 11, 2007 11:58 AMZoran Vujic Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    That works fine, thanks.

     

    Considering that there are multiple EDM query techniques (LINQ to Entities, Entity SQL, ObjectQuery, ...), is there any gudiance (article) which one to choose and when?

  • Thursday, October 11, 2007 4:33 PMDiego B VegaMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    To add to Danny's answer, here is something one of our developers pointed out (thanks Colin):

     

    Cast operations are reserved for database ‘convert’ operations. ‘Is’, ‘As’ and ‘OfType<T>’ on the other hand are available for nominal type operations. 

     

    Then, a more "linquesque" way to do this would be:

     

    var query = from ip in context.InvolvedParty
                where ip is OrganizationUnit
                && (ip as OrganizationUnit).Parent.ObjectId == organizationId
                select ip;

     

    Please, tell me if it works for you.

     

    Regarding your other question, I think the more general answer is (as Danny shows) that it is a matter of taste. A more technical criteria would be: If don't know beforehand what IQueryable implementation your queries will be targeting, you will probably want to stick to LINQ. Otherwise you can freely mix and match.

     

    - Diego

     

    Note: OfType<T> should actually work with any IQueryable implementation. It only makes your query look a little more bumpy Smile

  • Wednesday, October 17, 2007 12:59 PMZoran Vujic Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Yes, that query works, thank you all.

     

    var query = from ip in context.InvolvedParty
                where ip is OrganizationUnit
                && (ip as OrganizationUnit).Parent.ObjectId == organizationId
                select ip;