none
Navigation Properties don't expose Id correctly for lookups

    Question

  • It appears the exposure of foreign keys from a main table to a lookup table does not expose the referencing key to the lookup table.  Rather the link references the entity from the main table and forces the client to lookup via a URL.

    By using expand I can bring the data through but it is extremely verbose and bloats the message.  We have main tables with 10-15 lookup fields.  So, I would have to expand every field to just get the referenced Ids.

    This design prevents a client from caching lookup tables and just using the id to reference into them.

    The only workaround I can find is to create a view and hand modify the edmx file to workaround the EntityKey bug where pulling a view into EDM creates many EntityKeys.  Then, once this is done the client will still not understand the relationships.

    The model seems broken here. I think there needs to be a middle ground that allows the relationaship to come through in the main entity as a link that references the lookup entity.

     

    So, today it looks like this:

    <entry> 
        <id>http://localhost:1606/Tracetastic.svc/trace(guid'd397ffda-58a3-4e92-b607-0035b6322046')</id>   
        <link rel="edit" title="trace" href="trace(guid'd397ffda-58a3-4e92-b607-0035b6322046')" />   
        <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/application" type="application/atom+xml;type=entry" title="application" href="trace(guid'd397ffda-58a3-4e92-b607-0035b6322046')/application" />   
        <content type="application/xml">  
        - <m:properties> 
              <d:id m:type="Edm.Guid">d397ffda-58a3-4e92-b607-0035b6322046</d:id>   
              <d:message_text>Received WCF Request message on net.tcp://localhost:7766/FrameworkTests/1.0/ChannelTest</d:message_text>   
              <d:process_number m:type="Edm.Int16">8888</d:process_number>   
              <d:application_domain_number m:type="Edm.Int16">3</d:application_domain_number>   
          </m:properties> 
        </content> 
      </entry> 
     

    Note the href="trace(guid'd397ffda-58a3-4e92-b607-0035b6322046')/application"

    This forces a call back to the server to lookup the id in application.

    I believe this would be a lot better:

      - <entry> 
        <id>http://localhost:1606/Tracetastic.svc/trace(guid'd397ffda-58a3-4e92-b607-0035b6322046')</id>   
        <link rel="edit" title="trace" href="trace(guid'd397ffda-58a3-4e92-b607-0035b6322046')" />   
        <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/application" type="application/atom+xml;type=entry" title="application" href="application(1)" />   
        <content type="application/xml">  
        - <m:properties> 
              <d:id m:type="Edm.Guid">d397ffda-58a3-4e92-b607-0035b6322046</d:id>   
              <d:message_text>Received WCF Request message on net.tcp://localhost:7766/FrameworkTests/1.0/ChannelTest</d:message_text>   
              <d:process_number m:type="Edm.Int16">8888</d:process_number>   
              <d:application_domain_number m:type="Edm.Int16">3</d:application_domain_number>   
          </m:properties> 
        </content> 
      </entry> 

    Note the href="application(1)" 

    Or this would be the cleanest:

      - <entry> 
        <id>http://localhost:1606/Tracetastic.svc/trace(guid'd397ffda-58a3-4e92-b607-0035b6322046')</id>   
        <link rel="edit" title="trace" href="trace(guid'd397ffda-58a3-4e92-b607-0035b6322046')" />   
        <content type="application/xml">  
        - <m:properties> 
              <d:id m:type="Edm.Guid">d397ffda-58a3-4e92-b607-0035b6322046</d:id>   
              <d:message_text>Received WCF Request message on net.tcp://localhost:7766/FrameworkTests/1.0/ChannelTest</d:message_text>   
              <d:process_number m:type="Edm.Int16">8888</d:process_number>   
              <d:application_domain_number m:type="Edm.Int16">3</d:application_domain_number>   
              <d:application_id m:type="Edm.Int16" href="application(1)>1</d:application_id>   
          </m:properties> 
        </content> 
      </entry> 

    Let me know if there is some sort of workaround to this.

     

     


    Scott Prugh
    Wednesday, January 28, 2009 3:57 PM

All replies

  • No no we dont tell you the answer, you have to pay for this kind of support
    --------------joking aside

    Hi Scott Prugh

    The purpose of Ado.Net Data Services is to give an RESTful interface for addressing resources over the web, the associations which they called (other name is navigational property) are not like Entity Framework properties this is by design, it was required that Ado.Net Data Service provided a simple interface where the client was not required to use any Complex types like the entity framework does (main reason why we dont have complete object change tracking). The client is able to, if using .net, create POCO objects (Plain Old CLR Objects) that meet the criteria of the entities (IE have all the properties) and nothing else.

    Another thing to bear in mind is that you are dealing with a object conceptual model of the database which in theory will not look anything like the tables. The entity framework only include the EntityKeys because they support complete object change tracking.

    "The model seems broken here. I think there needs to be a middle ground that allows the relationaship to come through in the main entity as a link that references the lookup entity."

    If you were to do that you would be breaking the conceptual modal because the navigational properties have specific names and they represent actual tables on the back end that contain their own key values.

    You would be basically ignoring the Association taking the control over it from the client.

    And that is not what Ado.Net Data Services is about.

    Think like this: Your are not dealing with primitive keys anymore what you actually have is objects.

    So you know the Data Services Client Context will not create instances of the Associations or LinkDescriptors (accessed by the property Links on the client context) until you context.LoadProperty("") or you .Expand the property. If you want to be able to deal with this in different way you will need to transform the atom feed to look like what you want and create a new client data service context class to manage this.

    PS.: News flash the Entity Framework on 2010 visual studio which will contain .net 4.0 will not build up on the Complete Change tracking which the current version has, it will still be supported but going forward they are going to implement the POCO style and go even futher and implement the IPOCO (Interface Plain Old CLR Object).

    Daniel Portella Blogger from hell http://undocnet.blogspot.com
    If this post answers you question please mark as the answer.

    Daniel Portella - http://undocnet.blogspot.com - This posting is provided "AS IS" with no warranties, and confers no rights.
    Wednesday, January 28, 2009 8:28 PM
  • I understand the argument of "purest RESTful concepts" but this doesn't seem usable or scalable.  Basically for this scenario I would have to expand the descriptions for each lookup property making the message size grow to 10x its size.

    I really think something is off here.  Astoria is being sold as a easy way to surface data via ATOM/XML.  There seem to be so many limitations to it's model that it is unusable. In this case I am exposing almost 1-1 a relational model for end clients

    I was hoping not to have to hand code or write my own generator for REST services for simple scenarios like this.  Sadly I am finding that this is not the case.

     


    Scott Prugh
    Wednesday, January 28, 2009 9:10 PM
  • No no we dont tell you the answer, you have to pay for this kind of support
    --------------joking aside

    Hi Scott Prugh

    I share some of feelings and pains me to say we have to wait for the next version to hopefully make this better.

    But there are work arounds

    (I am really annoyed because i was writting you a nice post but my browser died on me so i lost what i was going to say so apologies if this one seems incomplete with out nice explanations on the links)

    Firstly read this guy post about associations and implement his method if you like but i have a better way to do it.

    http://blogs.msdn.com/phaniraj/archive/2008/10/23/working-with-associations-in-ado-net-data-services-part-2.aspx

    Secondly

    Read up the other post made by the same guy

    http://blogs.msdn.com/phaniraj/archive/2008/12/11/customizing-serialization-of-entities-in-the-ado-net-data-services-client-library.aspx

    implement this but again there is better ways to do the same thing we can talk about it here.

    and 3rd

    If you really want the reference ids you need to hook up to the ReadingEntity event on the data service context and get the associations from the atom feed and save them on your object. in way you can get the same functionality used by the entity framework (the reference keys) if you make use the the custom serialization stuff talked at the first link. I can post an example project on my blog so you can have a look at it.

    Dont give up on Ado.Net Data Services just yet and Ado.Net Data Services is an easy way to surface data "in the microsoft way" any other way you have DIY (Do It Yourself) way where the hooks on the client toolkit and service operation come in handy. And bear in mind that the guy on the team developing this are always looking to new concepts and way of doing things so I would wait until the next version comes along for it will hold many surprises.

    Daniel Portella
    Blogger from hell
    http://undocnet.blogspot.com
    If this post answers you question please mark as the answer.

    Daniel Portella - http://undocnet.blogspot.com - This posting is provided "AS IS" with no warranties, and confers no rights.
    • Proposed as answer by Daniel Portella Thursday, February 12, 2009 12:03 AM
    Wednesday, January 28, 2009 9:50 PM
  • No no we dont tell you the answer, you have to pay for this kind of support
    --------------joking aside

    Hi Scott Prugh

    You should read up my first post on this forum.


    Daniel Portella
    Blogger from hell
    http://undocnet.blogspot.com
    If this post answers you question please mark as the answer.

    Daniel Portella - http://undocnet.blogspot.com - This posting is provided "AS IS" with no warranties, and confers no rights.
    Wednesday, January 28, 2009 9:55 PM
  • If you just want the keys of the relationships, you can use the following url to fetch it: http://.../trace(guid'd397ffda-58a3-4e92-b607-0035b6322046')/$links/application. This works for both reference and collection navigation properties.

    But the V1 client doesn't support this and also, you can't this in a single request like the example you were suggesting (unless you want to batch the 2 request together and handle the batch response).

    The response to this url looks something like this:

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <uri xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">http://.../application(1)</uri>

    For collections, it will look something like this: (assuming that application would have been collection property)

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <links xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">
        <uri>http://.../application(1)</uri>
        <uri>http://.../application(2)</uri>
        ...
    </links>

    Hope this helps.

    Thanks
    Pratik


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Wednesday, February 04, 2009 7:43 PM
    Moderator