Errata

Programming Entity Framework

Errata for Programming Entity Framework

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
Printed Page x
x

NOTE TO ERRATA SUBMITTERS (May 14):
I wanted to be sure you knew that am not ignoring the new submissions. I have been waiting to get a copy of the 2nd Printing of the book (which contains corrections) so that I can verify which of the newly submitted errata has already been fixed before I process it.

Julie

Julia Lerman
Julia Lerman
 
May 16, 2009 
Printed Page pgs 373-378
UnpaidReservations walkthrough

Julie,
After spending some time getting the UnpaidReservations Defining Query to work as defined on pages 373-378 I almost gave up. I searched and found the updated edmx file that is included in the seperate download for chapter 14. After comparing and modifiying my edmx through the xml editor was I able to get the example to work.

The Chapter 14 copy of the BAModel.edmx had a couple of attributes that make the UnpaidReservations work.

The association mapping in the C-S for example should be

<AssociationSetMapping Name="ReservationUnpaidReservation" TypeName="BAModel.ReservationUnpaidReservation" StoreEntitySet="UnpaidReservations">
<EndProperty Name="UnpaidReservation">
<ScalarProperty Name="ID" ColumnName="ID" /></EndProperty>
<EndProperty Name="Reservation">
<ScalarProperty Name="ReservationID" ColumnName="ReservationID" />
</EndProperty>
<Condition ColumnName="ReservationID" IsNull="false"/>
</AssociationSetMapping>

The condition is critical

Another item is the Entity Type for the UnpaidReservation in the SSDL should be

<EntityType Name="UnpaidReservation" >
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="int" Nullable="false" />
<Property Name="ReservationID" Type="int" Nullable="true" />
<Property Name="PaymentTotal" Type="money" Nullable="false" />
<Property Name="Cost" Type="money" Nullable="false" />
</EntityType>

There is also a subtle change in the DefiningQuery

<EntitySet Name="UnpaidReservations" EntityType="BreakAwayModel.Store.UnpaidReservation">
<DefiningQuery>

SELECT r.reservationid AS ID, SUM(amount) AS PaymentTotal,
MIN(events.[TripCostUSD]) AS cost,r.reservationID
FROM reservations r
JOIN payments p ON r.[ReservationID]=p.[ReservationID]
JOIN events ON r.[EventID]=events.[EventID]
GROUP BY r.[ReservationID]
HAVING SUM(amount)&lt;min(TripCostUSD)
UNION
SELECT r.reservationid, 0,MIN(events.[TripCostUSD]) AS cost,r.ReservationID
FROM reservations r
JOIN events ON r.[EventID]=events.[EventID]
WHERE r.[ReservationID] NOT IN (SELECT reservationID FROM payments)
GROUP BY r.[ReservationID]
</DefiningQuery>
</EntitySet>

I am not sure if I have listed all of the changes nessesary or in the correct order to correct the issues. Would it be possible to perhaps update the process in the errata so others can work the example.

I am enjoying the book and am impressed with the breadth of the subject matter. It must have been a bit like eating a whale to produce a book such as this one. I look forward to purchasing the next version with hopefully the EF V4 changes.

~Ian

Ian B  Aug 06, 2009 
2
Above Figure 1.3 in the Sample Code (Both VB and C#)

Was reading the online version so the page number is probably incorrect as there is no page numbering in the online version.

I'm a little confused on where the "People" object is coming from in the sample Code:

From p In People.OfType(Of SalesPerson) Select p

In your Figure 1.2, the object is named "Person"

Should the sample code read:

From p In Person.OfType(Of SalesPerson) Select p

Am I miss understanding something?

Thank You.

Ming Hsueh  Aug 26, 2009 
Printed Page 80
bottom

On the bottom of page 80, you mention that the datatype for the contacts variable will show that it is a IQueryable of an "anonymous type". The type of the variable is actuall a System.Data.Objects.ObjectQuery of an "anonymous type". Of course, the ObjectQuery class implements IQueryable, but the correct type to show is System.Data.Objects.ObjectQuery


I love the book! Keep up the great work!

Bennie

Bennie Haelen  Aug 26, 2009 
PDF Page 80
4th paragraph

It says: "Anonymous types are generally used for on-the-fly types that won?t be used elsewhere
in the application. You cannot even pass them from one method to another."

Maybe at the time you write this book, you couldn't pass an anonymous type from one method to another. But now you can if the receiving method receives a dynamic.

Gustavo D?az  Mar 02, 2014 
Printed Page 85
example4-5 VBsection

change

PEF.CreateQuery(Of DbDataRecord)(strQ)

to

Dim Contacts = context.CreateQuery(Of DbDataRecord)(strQ)

Ceulemans P  Dec 26, 2009 
Printed Page 147
All Code samples

All references to ("WA") should be ("Washington").

Greg Lee  Aug 03, 2009 
Printed Page 148
Last Paragraph

The author states that if you delete an Entity from a model and later wish to recreate it you can: 2)Delete the Entity from the model and then edit the XML and delete its EntitySet and EntityType. I found that you also have to delete any navigation associations with any other entity otherwise the Designer won't be able to display the model any more.

Ruddy Santos  Aug 17, 2009 
Printed Page 176
Example 8.1. Querying for customers in the form load

The first line of code (i.e. var context = new BAGA.BAEntities();) will fail initializing a new BAObjects object using the connection string from the app.config file (I copied mine from the model project as suggested in the text) if you made the change discussed on page 167 concerning spliting out the schema files. This (as discussed on page 168) changes the app.config file's connection string to reflect the new location of the schema files, which is relative the model project, not the windows forms project.

I had to change my "Copy To Output Directory" property on the app.config file of the model project back to "Do not copy" and recompile so the schema files are embedded - then copy/paste the updated app.config file into the windows forms project.

Now the queries run as expected. I realize this may be just related to how I did it and followed along but I did not see anything mentionded about this so I thought I would submit it.

Thanks, Julia. I am enjoying the book and am looking forward to V2 of EF ... and your updated book, of course. :-)

Ron Landers  Jul 31, 2009 
Printed Page 177
top line

The C# line should be changed from

.Execute(Objects.MergeOption.AppendOnly);

to

.Execute(MergeOption.AppendOnly);

I don't know if this affects the VB code.

Mike Bridge  Jul 10, 2009 
Printed Page 186
Example 8-4 code - VB & C#

need to add the code to bind the customers data to the form:

customerBindingSource.DataSource = customers; // C# version

Greg Lee  Aug 04, 2009 
Printed Page 188
Second paragraph

The paragraph in question reads "To do this, you will need to create one new Object data source for the BAGA.Activity class and one for the BAGA.Destination class." This pretty much stopped me cold. I created the two object data sources, but couldn't get the drop downs shown in Figure 8-11 to display the choices. I finally went back to the project data sources window and added BAGA.Activity and BAGA.Destination and then set them to DataSource in the appropriate object data source. Then I was able to get the drop downs to work and set the appropriate properties. I'm not at all sure that this is what you intended as it seems my setting up those DataSources gets changed in the code below that paragraph. I'm a web programmer, not a windows forms programmer, so maybe this would be obvious to someone with that background, but it wasn't to me. Perhaps an expansion/clarification is in order?

BillHyde  Jul 03, 2009 
Printed Page 188
Testing the sample again

I had a problem with the secondary activity and secondary destination not being correct for the first record only - they were displaying the first entry in the combobox display lists instead of the correct values; all other records worked correctly.

I finally determined that is was due to setting the customerBindingSource.DataSource before setting the activityBindingSource.DataSource and the destinationBindingSource.DataSource.

Why is this the case? It seems like a nasty source of bugs and perhaps a warning would be worthwhile...

Greg Lee  Aug 04, 2009 
Printed Page 203
1st paragraph

you need to change the Customer query in the WIndow.Loaded event.

A think it should be :

you need to change the Trip query in the WIndow.Loaded event.

Ryohsuke Fujioka  Oct 10, 2009 
Printed Page 205
1st paragraph

Run the form and edit one of the trips, changing a date and the loadging.

But before close the form, I think we have to click the save button.

Ryohsuke Fujioka  Oct 10, 2009 
Printed Page 206
1st paragraph

The statement that ComboBox does not support updating is untrue: both SelectedValue and SelectedItem properties are two-way properties. In order to be useful for updating the related Location entity, one would rather bind to SelectedItem like this:

<ComboBox Name="comboBoxLodgingPartner" ... DisplayMemberPath="LodgingName" SelectedItem="{Binding ElementName=listBoxTrips, Path=SelectedItem.Lodging}" />

The assignment to SelectedValuePath can be dropped as well.

Matthias Schwalbe  Aug 12, 2009 
Printed Page 246
2nd paragraph

and will automatically deserialize it to a Customer object:

should be :

and will automatically deserialize it to a Contact object:

and VB code sammple should be :

Private Sub GetContactFromService()
Dim proxy =
New BreakAwayCommonService.BreakAwayCommonServiceClient
Dim contact = proxy.GetContact(21)
Console.WriteLine("{0} {1}", contact.FirstName.Trim,
contact.LastName.Trim)
End Sub

Ryohsuke Fujioka  Oct 10, 2009 
Printed Page 250
Example 10-1

VB
Partial Public Class BreakAwayEntities

should be :

Partial Public Class BAEntities

C#
public partial class BreakAwayEntities :

should be :

public partial class BAEntities :

Ryohsuke Fujioka  Oct 10, 2009 
Printed Page 253
1st note

ObjectContext also has a pair of Changed and Changing events.

should be :

EntityObject also has a pair of [Paoperty]Changed and
[Paoperty]Changing events.

Ryohsuke Fujioka  Oct 10, 2009 
Printed Page 254
3rd paragraph

In VB, select Address from the Class Name drop-down;

should be :

In VB, select Activity from the Class Name drop-down;

and

Choose OnAddressIDChanging and OnAddressIDChanged,

should be :

Choose OnActivityNameChanging and OnActivityNameChanged,

Ryohsuke Fujioka  Oct 10, 2009 
Printed Page 255
1st paragraph

This means you can impact whatever you wish about the Address entity in this business logic.

should be :

This means you can impact whatever you wish about the Activity entity in this business logic.

Ryohsuke Fujioka  Oct 10, 2009 
Printed Page 259
Column

It is true that we can't use enum value directly when building a Entitykey.

So the next code
new EntityKey("BAEntities.CustomerTypes", "CustomerTypeID",
CustType.Standard);
throw an ArgumentException that inform us that the third parameter is not Int32.

You said that unfortunately we had to write this code like next.
new EntityKey("BAEntities.CustomerTypes", "CustomerTypeID", 1);

But it's a pity we have to use such a magic numeber.

I think it's much better if we write this code like next.
new EntityKey("BAEntities.CustomerTypes", "CustomerTypeID",
(int)CustType.Standard);

Ryohsuke Fujioka  Oct 18, 2009 
Printed Page 263
Example 10-10

Dim custOnOtherEnd = CType(e.Element, Customer)

should be :

Dim contactOnOtherEnd = CType(e.Element, Contact)

and next page(264)

Partial Public Class Customer

should be :

Partial Public Class Contact

Ryohsuke Fujioka  Oct 10, 2009 
Printed Page 264
C# Code example

public Address()
{
this.CustomerReference.AssociationChanged +=
new CollectionChangedEventArgs(Add_CustRefChanged);
}

should be :

public Address()
{
this.CustomerReference.AssociationChanged +=
new CollectionChangedEventHandler(Add_ContactRefChanged);
}

and

private void Add_CustRefChanged(object sender,
CollectionChangeEventArgs e)
{
CollectionChangeAction act = e.Action;
Customer custOnOtherEnd = (Customer)e.Element;
//add your logic here
}

should be :

private void Add_ContactRefChanged(object sender,
CollectionChangeEventArgs e)
{
CollectionChangeAction act = e.Action;
Contact contactOnOtherEnd = (Contact)e.Element;
//add your logic here
}

and

public partial class Customer
{
public Customer()
{

should be :

public partial class Contact
{
public Contact()
{





Ryohsuke Fujioka  Oct 10, 2009 
Printed Page 264
2nd paragraph

An errata is already submitted for pg. 164. A second fix would be:

// Implementing AssiciationChanged
this.Contact.CustomerReference.AssociationChanged +=
new CollectionChangeEventHandler(CustomerReference_AssociationChanged);

and:

void CustomerReference_AssociationChanged(object sender, CollectionChangeEventArgs e)
{
CollectionChangeAction action = e.Action;
Customer customer = e.Element as Customer;
// Add logic here;
}

Bob Bedell  Oct 25, 2009 
Printed Page 277
Ist paragraph

Now you get to see the ObjectDataSource in action.

should be :

Now you get to see the EntityDataSource in action.

Ryohsuke Fujioka  Oct 10, 2009 
Printed Page 288
Example 11-2, 5th line

In Example 11-2, line 5 "AutoGenerateWhere=True" should be "AutoGenerateWhereClause=True"

BillHyde  Aug 20, 2009 
Printed Page 288
Example 11-2, 4th line

In Example 11-2, line 4 reads
'EntitySetName="Contacts" EntityTypeFilter="Customer"'
Setting EntityTypeFilter to Customer generates an error be cause it is not a type or derived type of EntitySet Contacts. Setting EntityTypeFilter to "Contact" or omitting it entirely removes the error condition.

BillHyde  Aug 20, 2009 
Printed Page 293
Item 3 under "Creating a Parent EntityDatasource ..."

On page 293 under the topic "Creating a Parent EntityDataSource ..." item 3 in the list states "Set the EntityDataSource's ConnectionString and EntityContainer to BAEntities." The word "ConnectionString" should be "Named Connection".

BillHyde  Aug 21, 2009 
Printed Page 294
select clause after 2nd paragraph and also in 3rd paragraph

On page 294 is a select between paragraphs 2 and 3 that has a where clause -- Where="count(select value r.ReservationID from c.Reservations as r) &gt; 0". The predicate of this clause "count..." when inserted in the "where" property of the EntityDataSource that is bound to the drop down list produces an error "'c.Reservations' could not be resolved in the current scope or context. Make sure that all referenced variables are in scope, that required schemas are loaded, and that namespaces are referenced correctly., near multipart identifier, line 9, column 41."

This seems to resolve if one drops the "c." in front of Reservations making the where property "count(select value r.ReservationID from Reservations as r)".

I have no clue why this works and the first one doesn't. When I look up the where property in MSDN it seems to preface most names by "it.". I tried that in this case and it doesn't work either. As someone said I am working with dark forces beyond by knowledge (or something like that).

BillHyde  Aug 21, 2009 
Printed Page 296
List item 3 under heading "Using a New EntityDataSource ..."

In list item 3 under the heading "Using a New EntityDataSource ..." change "From the GridView Tasks window" to "From the ListView Tasks window".

BillHyde  Aug 22, 2009 
Printed Page 299

I'm Sorry for my bad English because I am Japanese and usually not use English.

I bumped into the same problem that Joseph did.
The problem is that when I selected new item on dropdownList,
items of listBox changed but context of paymentsDS didn't be
recreated.(Creating event didn't be called.)
I found a workaround for this problem although it's not cool, but work at least.

First, I don't use AutoGenerateWhereClause and set Where parameter to
"it.Reservation.ReservationID=@Hoge" and set WhereParameters to asp:Parameter named Hoge, not asp:ControlParameter.
(All of these setting can be done from property window.)

<asp:EntityDataSource ID="PaymentDS" runat="server"
ConnectionString="name=BAEntities"
DefaultContainerName="BAEntities"
EnableInsert="True" EntitySetName="Payments"
=> Where="it.Reservation.ReservationID=@Hoge"
oninserting="PaymentDS_Inserting">
<WhereParameters>
=> <asp:Parameter DbType="Int32" DefaultValue="0"
Name="Hoge" />
</WhereParameters>
</asp:EntityDataSource>

2nd, to assign this parameter correct value, I manually wrote codes in 2 places.
One is at ContactDS's Selected event.
Two is at ListBox's SelectedIndexChanged event.
That's all. Only two sentences.

protected void ContactDS_Selected(object sender,
EntityDataSourceSelectedEventArgs e)
{
var contact = e.Results.Cast<Contact>();
var res = contact.First().Customer.Reservations;

if (res.Count > 0)
{
ListBox1.DataSource = res.ToList();
ListBox1.DataTextField = "tripdetails";
ListBox1.DataValueField = "ReservationID";
ListBox1.DataBind();
ListBox1.SelectedIndex = 0;

=> PaymentDS.WhereParameters[0].DefaultValue =
res.First().ReservationID.ToString();
}
}

protected void ListBox1_SelectedIndexChanged(object sender,
EventArgs e)
{
=> PaymentDS.WhereParameters[0].DefaultValue =
ListBox1.SelectedValue;
}

Thanks for the DefaultValue of Hoge Parameter is set to 0, in the other situation, paymentsListView is cleared automatically.

I think that your program is intrinsically correct, and this is a bug of Micorosoft.
This book is really wonderful!

Thanks.

Ryohsuke Fujioka  Oct 17, 2009 
Printed Page 308
last two lines on page

On page 308 the lines
Imports BAGA.BreakAwayModel
and
using BAGA.BreakAwayModel;

should be
Imports BAGA
and
using BAGA;

BillHyde  Aug 24, 2009 
Printed Page 309
Figure 12 - 5

I think Figure 12-6 is the wrong screen capture. Its showing the mapping for the OLD "FK_Customers_Activities" association mapping that was originally established in the EDM. The new association mapping, as shown in Figure 12-5, should be named "ActivityCustomer".

The reason this matters is that when one attempts Step 4 on page 308, the mapping details view will show Activity and Customer tables, not Activities and Customers tables. This is confusing because there are no Activity or Customer tables in the store. So is the mapping NOT using table names, but rather entity names due to the inheritance, or something???

Also, to get the properties dialog settings displayed in Figure 12-5, one can drag the Association Tool from Activity to Customer, instead of dragging the Association Tool from Customer to activity as explained in Step 1 on page 308. Dragging the Association Tool from Customer to Activity wil give you an association named CustomerActivity, not ActivityCustomer. While I don't suppose it really matters, confusion arrises here.

In short, pages 308 and 309 could use some revisiting.

Thank you.

Bob Bedell  Nov 01, 2009 
Printed Page 316
2nd numbered list - creating NonCustomer

On page 316 in the steps of creating the NonCustomer entity, there should be a mention that when one drags an entity from the toolbox to the design surface a property called "id" is created. This must be deleted prior to running the application or an exception noting a mapping error will be generated.

BillHyde  Aug 24, 2009 
Other Digital Version 338
2nd paragraph

In the second paragraph giving instructions for creating the entity data model for the simple POCO example, there is this sentence:

"Name the EntityContainer POCOEntities and select all tables".

If all the the tables and subsequent directions are followed, the example won't run. If only the Contact and Address tables are selected for the model, then after following the subsequent directions, the example runs fine. Bringing in all the tables brings in many more navigation properties than are covered in the example.

GREAT book, by the way!

-Barry

Barry Dieser  Feb 22, 2012 
Printed Page 340
C# code example

In the 'Using Complex Types' section, the following line of code won't compile:

AddressDetail addressDetail = contact.Addresses[0].Detail;

I get:

Cannot apply indexing with [] to an expression of type 'System.Data.Objects.DataClasses.EntityCollecton<BAModel.Address>'

So I went with:

AddressDetail addressDetail = contact.Addresses.Take(1).FirstOrDefault().Detail;

Works OK.

The second to last line of the C# code has:

contact.Addresses(0).Detail = newAD;

Sould be brackets instead of parentheses in C#, shouldn't it, but neither compile.

Bob Bedell  Nov 01, 2009 
Printed Page 345
Example 13-7

The code is assumed to fix the two-way relation between Address and Contact. But when the address is re-linked to a different contact, for example by calling
address.Contact = contact1;
address.Contact = contact2;
both contacts will have the address listed and the object invariant is compromised.
This can be prevented by either checking for address._contact == null at the start of both Contact.AddAddress() and Address.set_Contact().

Arthur van Dongen  Oct 07, 2011 
Printed Page 363
Example 13-2

The cumulative walk-through approach seems to be causing code to break more and more frequently the deeper one gets into the book.

In the section on page 362 "Query Stored Procedures and Inherited Types" the text reads: "The CustomersWhoTravelledinDateRange stored procedure returns all of the appropriate fields to match up with the Customer type."

Unfortunately it doesn't, because when we inherited Customer from Contact in the previous chapter, we changed the Customer TimeStamp field name to custTimeStamp to avoid a naming collision with the TimeStamp field in the Contact entity.

So when you run the code in 13-2, you get:

"The data reader is incompatible with the specified 'BAModel.Customer'. A member of the type, 'custTimeStamp', does not have a corresponding column in the data reader with the same name."

It was my understanding that the book, going forward, was going to use cumulative changes to the model, though its 'kinda hard to follow when these changes are supposed to be retained and when they are supposed to be discarded. The sentence or two indicating this is often easy to overlook. It would be nice if the code download contained more versions of the model as it is supposed to exist at various stages of the book, given that a lot of people (like me) are probably creating different copies of the model for different topics to keep functioning versions intact.

Anonymous  Nov 03, 2009 
Printed Page 367
Example 14-1

When using the download from Chapter 8 for the BreakAwayModel with this section of code I receive an error on context.SaveChanges():

The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.

It appears that without setting:

newCust.AddDate = (some DateTime variable)
newCust.ModifiedDate = (another DateTime variable)

I receive this error because they were set as Nullable = false.

Anonymous  Aug 02, 2011 
Printed Page 377
Example13-9

The UnpaidReservations DefiningQuery walk-through in Chapter 13 isn't implemented correctly. However, the Chapter 14 model contains a correct implementation of the UnpaidReservations DefiningQuery. If you run the Example 13-8 code againt the Chapter 14 model, you will get the correct output.

Caveat: In the Chapter 14 model I unzipped, the Activity entity was missing the Catagory property. I needed to add the Category scalar property to the Activity entity, then map it to the Activities.Category property in the store Activity table. Then everything built and ran fine.

Bob Bedell  Nov 05, 2009 
Printed Page 431
Example 14-28

Ran into some glitches with the Deleting Reservations logic for the UpdateCustomer method.

The first is a small code error, the second is some weird databinding behavior.

First, in the WPF service UpdateCustomer method, the following is given for the portion of the method that deletes Reservations from the reservation delete list:

var resid = cust.ReservationsToDelete[0];

it should be:

var resid = cust.ReservationsToDelete[resi];

The former will only delete the first reservation in the list; the latter will delete multiple reservations in one call to UpdateCustomer.

Second, in the client, the DelRes_Click calls ShowReservations() to refresh the reservations list box. Works fine for comboBox1_SelectedIndexChanged and AddRes_Click. For some odd reason, when calllled from DelRes_Click, instead of diplaying reservation TripDetails, the listbox diaplys:

Chapter14ClientCS.BAWCFService.Reservation
Chapter14ClientCS.BAWCFService.Reservation
Chapter14ClientCS.BAWCFService.Reservation

- databinding's default behavior when it calls an object's ToString() method, and ToString() isn't overridden.

I fixed it by binding the listbox's DataSource property first, then binding ValueMember and DisplayMember:


listBox1.DataSource = _currentCustomer.Reservations;
listBox1.ValueMember = "ReservationID";
listBox1.DisplayMember = "TripDetails";

instead of:

listBox1.ValueMember = "ReservationID";
listBox1.DisplayMember = "TripDetails";
listBox1.DataSource = _currentCustomer.Reservations;

If anyone has an explanation for that one, I'd love to here it on this book's forum.



Bob Bedell  Nov 07, 2009 
Printed Page 458
Last Paragraph

"This is why these extra entries exist - one for Contact, one for the related Trip, and one for the UnpaidReservtion entity (which you created in Chapter 13)."

It appears that only TWO extra entries exist. There isn't one for the UnpaidReservation entity.

It appears that the placeholder entries are only created in cases where the Reservation entity is on the 'Many' side of a relationship.

So there is a key into the Contacts and Trips entity sets, but not to the Payments or UnpaidReservations entity sets, where the Reservation entity is on the '1' or '1..0' side of the relationship.

I'm using the Chapter 14 version of the model.

Bob Bedell  Nov 08, 2009 
Printed Page 545
Example 17-22

Missing a cast.

EntityKey currRelEndA = relEntry.CurrentValue[0] as EntityKey;
EntityKey currRelEndB = relEntry.CurrentValue[1] as EntityKey;

Bob Bedell  Nov 14, 2009 
Printed Page 561
Example 17-41 Creating a list of navigation property names

There is no need for this list.

We can work directly with the ReadOnlyMetadataCollection returned by EntityType.NavigationProperties.

private static string BuildSingleEntityQuery(string entityReference,
string entityCollection,
int entityId,
MetadataWorkspace metadataWorkspace)
{
string containerName = metadataWorkspace.GetItems<EntityContainer>(DataSpace.CSpace)
.First().Name;
string namespaceName = metadataWorkspace.GetItems<EntityType>(DataSpace.CSpace)
.First().NamespaceName;

EntityType entityInfo = metadataWorkspace.GetItem<EntityType>(
namespaceName + "." + entityReference, DataSpace.CSpace);
// Get navigation properties.
ReadOnlyMetadataCollection<NavigationProperty> navigationProperties =
entityInfo.NavigationProperties;

string singleKeyName = entityInfo.KeyMembers[0].Name;

// Build the eSQL string.
StringBuilder eSqlQuery = new StringBuilder();
eSqlQuery.Append("SELECT entity");

// Add each navigation property to the projection.
foreach (var name in navigationProperties)
{
eSqlQuery.Append(", entity." + name);
}

eSqlQuery.Append(" FROM " + containerName.Trim() + "." + entityCollection + " AS entity");

eSqlQuery.Append(" WHERE entity." + singleKeyName + " = " + entityId);

return eSqlQuery.ToString();
}

Bob Bedell  Nov 15, 2009 
Printed Page 711
Top of Page Code

Hello,

Custom property setters on the Customer are being used for the Primary and Secondary ID's of the Activities and Destinations. If there were no PrimaryActivity, would the PrimaryActivity always be null? If so could we do the following within the PrimaryActivityID property of the Customer:

if(PrimaryActivity == null)

instead of:

if (PrimaryActivityReference.EntityKey.EntityKeyValues.Count() > 0)

Perhaps the best approach is to use the longer code. But I'm always looking for ways to streamline, while not adding bugs.

Thanks,
Mark

Mark Phillips  Jun 12, 2009