Shawn Wildermuth - MVP (C#)

I can't find any explanation of what I should be doing with this. The problem revolves around the following query:

SELECT c FROM Northwind.Customers as c

When I execute this query via ObjectServices (e.g. ObjectQuery<>) it returns Customers as expected. When I execute it via the EntityClient managed provider, it returns a BridgeDataRecord as the first column of each result. Can someone point me to where this is documented or how we can use this class




Re: ADO.NET (Pre-release) BridgeDataRecord?

Daniel Simmons - MSFT

If you do the query above at either Object Services or EntityClient, then you are creating a query which returns a series of rows each of which has a single column which contains an entity. At the Object Services layer the representation of an entity is an object that is the entity, but at the EntityClient layer, the representation of an entity is a DataRecord which contains columns that make up the values of that entity. BridgeDataRecord is just a class which inherits from DbDataRecord and provides the concrete implementation of the data records returned from EntityClient (sometimes a single level and sometimes multiple levels nested inside each other). This is just like SqlClient will return a DataRecord that is SqlDataRecord or something like that.

This is very similar to what would happen if you were to do the query

SELECT c.ContactName FROM Northwind.Customers as c

In this case you would receive a data record which contains a single column that has a single column with that string property (regardles sof whether you are querying at Object Services or EntityClient.

As an alternative, you could change your query to:

SELECT VALUE c FROM Northwind.Customers as c

-or-

SELECT VALUE c.ContactName FROM Northwind.Customers as c

In either of these cases instead of retrieving a DataRecord with a single column containing either the entity (object or record depending on layer you query against) you would just directly retrieve the value. So this means that at the Object Services layer you would retrieve an enumeration of entity objects or an enumeration of strings and at the EntityClient layer you would retrieve DataRecords directly contianing the entity properties or containing the strings.

One implication of this is that while a regular SELECT statement can have multiple things listed in the projection of values retrieved (you can retrieve a customer and an order in each record or a ContactName and a phone number or whatever), but in the SELECT VALUE statement you can only specify one thing since there is no outer record to hold the set of values.

- Danny






Re: ADO.NET (Pre-release) BridgeDataRecord?

Shawn Wildermuth-MVP

Sorry for not replying to this soon as I've been distracted with other stuff...but...

While this information is helpful, it doesn't look like the right implementation. When I use the EntityClient provider and execute that query, what I am getting is confusing:

  • I execute the query and get a DbDataReader...
  • Each row of the DbDataReader is a DbDataRecord...(all good so far...)
  • In the *first* column of the DbDataRecord is another DbDataRecord.

This nesting seems unecessary unless I am missing something. The way you return this information is completely unbindable as the top 'DbDataReader' becomes a meta-reader.

Now I am fully aware that using SELECT VALUE returns the entities and that using ObjectServices solves this, this is still confusing...especially to new users.

In the article I am current writing (on the EntityClient Provider), I am trying to explain how this is just an ADO.NET Managed Provider so you can use the EDM in non-entity scenarios (e.g. report writers), but if you return these confusing nested objects it will not work at all.

I am happy to take this offline and have a conversation with team members if needed.






Re: ADO.NET (Pre-release) BridgeDataRecord?

Daniel Simmons - MSFT

Well, I understand that this takes some getting used to, but it's fairly fundamental to the design of eSQL. It's part of making the language more regular. This regularity shows up in a few different ways:

1) Whenever you make a query that begins with just "select" (not "select value") you will receive back a reader where each row is a DbDataRecord that has exactly the number of columns in it as the number of entries in your projection list. Each one of those entries can be a scalar or something more complex, but there will be precisely that number of columns.

2) Any entry in the projection list can not only be a scalar or a more complex type, but it can be a singleton or a collection. In EntityClient, if something is a collection, then it will show up as a DataReader. These collections can come from something like navigating a relationship and the other side being a collection, they can be created with nested subqueries or they can even just be a static list specified as part of the query text.

3) Whenever you make a query that begins with "select value" then your projection list must contain only one thing, and the result that you get back will be a reader where each row has only the one thing that you requested. That one thing could be a scalar or it could be something more complex like an entitiy in which case the records in the reader will have multiple columns, but either way each record in the reader will only contain the one thing requested so there will be no extra nesting.

NOTE: If you make a query that only has one thing in the projection list, then the reader will, on the surface, look the same whether you do "select" or "select value", but the metadata for each row returned in that reader will be different--for "select" the metadata will tell you that the row contains a record which happens to have one column in it which is your scalar, but for "select value" the metadata will tell you that the row contains just a scalar, and it is exactly this metadata which the object services layer uses to determine how to handle the results.

So, I'm not sure if this really resolves your issue of explaining this to people, but there has been some careful thinking put into the way this part of entity SQL works and the way that it shows up in EntityClient. Yes, EntityClient is an ADO.Net provider, but because it is built around entity SQL and the Entity Data Model which have both nesting and polymorphism built into them at a very fundamental level, the data readers returned from EntityClient do require some extra handling unless you write your queries very carefully to return only flat, non-polymorphic results.

- Danny






Re: ADO.NET (Pre-release) BridgeDataRecord?

Shawn Wildermuth-MVP

I think that is a fair comprimise between complexity and functionality. Thanks for the detailed explanation!