Wednesday, July 30, 2008

I have been writing gobs of Extension methods for entity Framework through the course of writing my book.

I was inspired by this forum thread to create extension methods to overload existing methods in the APIs.

One pattern that was annoying me was that frequently when I'm using the GetObjectStateEntries method of the ObjectStateManager, I want to filter on a type. It only meant building a linq expression with the method in it

Dim CustomerEntries= From entry _
                                    In objStateMgr.GetObjectStateEntries(EntityState.Added Or EntityState.Deleted _
                                          Or EntityState.Modified Or EntityState.Unchanged) _
                                    Where entry.Entity.GetType Is Customer

So two things about this were bugging me.

The first is I always have to list out all of those entries. Sometimes I only want one or two, so it's good to build the list.

The second is that I always have to write a query.

So, I created a few overloads to the method.

The first takes no parameters, and returns all of the entries, regardless of EntityState

<Extension()> _
Public Function GetObjectStateEntries(ByVal osm As Objects.ObjectStateManager) _
   
As IEnumerable(Of Objects.ObjectStateEntry)
  Dim typeEntries = From entry As Objects.ObjectStateEntry _
                  
In osm.GetObjectStateEntries(EntityState.Added Or EntityState.Deleted _
                      Or EntityState.Modified Or EntityState.Unchanged)
  Return typeEntries
End Function

Now I can just call GetObjectStateEntries and get all of them without having to specify the four entity state enums.

The second returns all objects of a particular type. Having the overload for the generic type is more discoverable for people like me.

<Extension()> _
Public Function GetObjectStateEntries(Of TEntity)(ByVal osm As Objects.ObjectStateManager) _
    
As IEnumerable(Of Objects.ObjectStateEntry)  
  Dim typeEntries = From entry As Objects.ObjectStateEntry _
                    In osm.GetObjectStateEntries(EntityState.Added Or EntityState.Deleted _
                      Or EntityState.Modified Or EntityState.Unchanged) _
                    Where entry.Entity Is TEntity

  Return typeEntries 
End Function

Now I can get all entities of a particular type without having to build a query.

GetObjectStateEntries(Of Customer)

The last takes the EntityState parameters and filters on a particular type.

<Extension()> _
Public Function GetObjectStateEntries(Of TEntity)(ByVal osm As Objects.ObjectStateManager, _
         ByVal state As EntityState) As IEnumerable(Of Objects.ObjectStateEntry) 
  Dim typeEntries = From entry As Objects.ObjectStateEntry _
                    In osm.GetObjectStateEntries(state) _
                    Where entry.Entity Is TEntity
  Return typeEntries
End Function

So I can use GetObjectStateEntries it's "normal" way, except I can include the type as well as filtering on state.

GetObjectStateEntries(Of Customer)(EntityState.Unchanged)

(These are in Chapter 14 along with their C# versions. :-))

Wednesday, July 30, 2008 9:21:05 AM (Eastern Standard Time, UTC-05:00)  #     |  Comments [0]  | 
 Monday, July 28, 2008

My friend's husband is a biologist and researcher at Cornell's Ornithology Lab and pretty well known in his field.

NPR played some clips that he recorded in Guatemala of Howler Monkeys and Toucan's on their feature, Sounds from the Wild. Cool.

Monday, July 28, 2008 12:08:54 PM (Eastern Standard Time, UTC-05:00)  #     |  Comments [1]  | 

Yesterday I made my third attempt of the summer to get up the the 2.75 mile climb of the App Gap. I have to ride uphill 3 miles just to get to the "starting point".

Here's what the elevation looks like from the starting point to the peak.

The first arrow is where I've bailed previously (twice). The second is about where I got to last night (2.5 miles). The yellow line is the peak. You can see that the last bit is a freaking wall.

appgap

I almost bailed at the same spot again last night but goaded myself to the next sign (50 ft away) then to the end of the guard rail (another 100 ft) and then to the picnic tables (another 200 ft). Then once I got past the picnic tables, it eased up again and I got all the way to the last wall, but there was just no way I could do the last little bit. Now that I realize that it gets easier past that first spot, I can definitely push myself through it again.

However, since I had started out hoping to just get past my last bail point and maybe to the picnic tables, I was surprised to get as far as I did. I wasn't the least bit disappointed not to get to the top because that wasn't my goal.

On the way up, I saw my neighbor, Joe, flying down on his bike. He does the gap ride all the time. It's not big deal at all for him. :-) It's his little ride for when he doesn't have time to go out for a real ride.

One of the things that helped me was deciding to just go right up into my granny gear at the start - save my strength, not my gears.

Okay back to work.

Monday, July 28, 2008 9:32:03 AM (Eastern Standard Time, UTC-05:00)  #     |  Comments [2]  | 

While I continue to enjoy being at home in Vermont for the whole summer, I have to look past this fantasy to the reality of my upcoming travel where I get to share the Entity Framework (and Silverlight) love around the world. I have yet to get this all onto my website schedule.

Here's what's on my schedule:

I'm also planning to attend Microsoft's PDC 2008 in Los Angeles

Then I will rest up for the winter in Vermont. :-)

Monday, July 28, 2008 7:22:48 AM (Eastern Standard Time, UTC-05:00)  #     |  Comments [0]  | 
 Saturday, July 26, 2008

There are two web apps based on mapping APIs - one uses Google and the other uses Virtual Earth - that I use frequently. It's a long way from what you could do with Virtual Earth when I started dabbling when it first came out. Read more.

[A New DevLife Post]

Saturday, July 26, 2008 7:00:49 PM (Eastern Standard Time, UTC-05:00)  #     |  Comments [0]  | 

Mike has posted a bunch of ADO.NET Data Services videos up on Channel 9.

Even though I haven't had a chance to check them out yet, it's easy to presume that these are going to be as great as all of his other screencasts.

http://channel9.msdn.com/tags/UK

He says there are more to come.

Enjoy.

Saturday, July 26, 2008 12:11:01 PM (Eastern Standard Time, UTC-05:00)  #     |  Comments [0]  | 
 Friday, July 25, 2008

I learned a neat ESQL trick from Danny Simmons today.

The most basic Entity SQL expression is one that would simply query for a single entity with no filters, no projection etc.

context.CreateQuery<Customer>("SELECT VALUE con FROM MYEntityContainer.Contacts AS con")

You can actually express the string using only the target collection:

context.CreateQuery<Customer>("MyEntityContainer.Contacts")

and EF will build the same command tree as it does for the first expression.

Friday, July 25, 2008 8:45:30 PM (Eastern Standard Time, UTC-05:00)  #     |  Comments [0]  | 

Software Developer

Vertek Corporation, a leading provider of telecommunications services located in Colchester, Vermont is seeking a Software Developer to join our growing Software Development team.

The Software Developer will support our existing products and help Vertek build our next generation workflow platform which leverages Red Hat’s jBPM workflow engine with a Google Web Toolkit (GWT) Web 2.0 presentation framework. The ideal candidate will have full/hands-on SWDLC experience designing, building, testing, deploying and supporting n-tier applications. Candidates should have experience with two or more of the following technologies: GWT, JBoss, JUnit (or NUnit), Hibernate, Subversion, .NET, Business Objects (universe creation). They should have hands-on experience with all of the following: n-Tier development, SQL Server 2000+ and/or Oracle 10g, Java, Eclipse, Ant and web development. Experience developing large scale/enterprise applications in a Continuous Integration environment is a plus.

Required experience and education: 1-3 years, bachelor’s degree in computer science or related discipline (relevant co-op experience may be applied). Java, Oracle and/or Microsoft certifications are a plus.

E-mail resume to: HR@Vertek.com

Friday, July 25, 2008 8:20:50 PM (Eastern Standard Time, UTC-05:00)  #     |  Comments [0]  | 

Kathleen Dollard is building a list for C# devs who are going to be building projects in VB. Read more

[A New DevLife Post]

VB
Friday, July 25, 2008 2:14:49 PM (Eastern Standard Time, UTC-05:00)  #     |  Comments [2]  | 
 Friday, July 18, 2008

I'm just a little busy so I'll probably skip this little run...

The Vermont 100

Friday, July 18, 2008 9:06:58 AM (Eastern Standard Time, UTC-05:00)  #     |  Comments [0]  | 
 Tuesday, July 15, 2008

I have finally finished what has been, so far, the most difficult chapter of my book. It is a chapter about Relationships and Associations in the Entity Framework. Relationships as a first class citizen in an API is a pretty novel thing for me (and many) and judging from the percentage of questions in the forum about relationships, I think it's one of the most confusing and complicated pieces of the framework. Complexity is not a bad thing, and it certainly is a fascinating adventure. There are so many rules that exist in order to maintain the integrity of the relationships so that they can do their work. And many of the rules are far from intuitive.

I've been struggling to understand what's behind all of these rules so that don't have to be rules to be memorized but instead become logical ways for me to work with entities. Then the job was to try to digest that and explain it in a way that is comprehensible to others. It has meant a lot of research, digging through the forums relentlessly,  reading blogs and lots and lots and lots of experimenting. Because there's really not much else out there. Oh and of course bugging the hell out of Danny Simmons and some other saints on the EF team.

The scary part is that every time I opened up door of understanding, I discovered a host of new things that I realized needed explaining as well.

I finally had to let it go and "throw it over the wall" to the reviewers.

I feel like I deserve it to be all downhill from here, but somehow I just don't think it's going to work out that way!

Tuesday, July 15, 2008 9:46:05 PM (Eastern Standard Time, UTC-05:00)  #     |  Comments [0]  | 
 Monday, July 14, 2008

Bill McCarthy's latest garden post made me realize I hadn't taken any pics in a while so here's what's going on in mid July.

The hostas are blooming.

veggiepatch 001 

The clematis are lush.
summer visit 010

There's a lot going on in the front garden - rubekia, foxglove, daisies, mallow, astilbe, roses, russian sage and so much more.summer visit 011

The Hollyhocks are starting to open.

summer visit 014

Down by the road the menarda (bee balm) is open all along the fence. summer visit 017

summer visit 016

For some reason the daylilies along the fence haven't opened while they have opened everywhere else.

summer visit 018

I'm not sure how this sunflower got into the hanging basket, but I'll have to get it out of there soon!summer visit 028 

 veggiepatch 002

The veggie garden needs major weeding but it's lush with veggies - though we're only getting lettuce (still) and waiting for everything else to come into season. Here are some peas that are getting ready. There's plenty more but the weeds are too embarrassing, so no more pictures.veggiepatch 003

Monday, July 14, 2008 3:21:34 PM (Eastern Standard Time, UTC-05:00)  #     |  Comments [1]  | 

But it didn't make Money's top 100 list because they only looked at cities with population of 50,000 - 300,000. Here's their criteria.

Burlington is a little under 40,000.

Kathleen Dollard's home town of Ft. Collins CO was #2 on the list.

But I still think Burlington is one of the best small cities in the U.S, but since we like to keep it that way (small) maybe it's better that we weren't on the list after all. ;-)

Unfortunately, there are other factors that might kept us out of the top of that list had the population filter not excluded us. The cost of living here is higher than average especially when you put it next to the salaries.

But the quality of life is what we're here for and we all make due the best we can.

Monday, July 14, 2008 8:21:27 AM (Eastern Standard Time, UTC-05:00)  #     |  Comments [1]  | 
 Sunday, July 13, 2008

Someone posted a question in the Entity Framework MSDN forum asking for an example of overriding SaveChanges. I thought I had posted one in an early thread but couldn't find it. Nor could I find an obvious example anywhere on the web, so I thought I would put one here on my blog.

There aren't a lot of public events on the classes created from the code generated classes of an Entity Data Model. But you can override the ones that exist.

ObjectContext exposes SavingChanges.

EntityObjects expose PropertyChanged and PropertyChanging and there's a pair of these for each property in an entity. E.g. for Customer, you'll get OnCustomerIDChanged and OnCustomerIDChanging.

Because these are all partial classes, you need only to create new code files that extend the partial classes. I create a separate code file for each class.

In my sample project which hosts a model for AdventureWorks, therefore, I have a code file named AWEntities (.vb or .cs) that extends the AWEntities class.

Here's an example of that class, which does a few things to my entities when I call SaveChanges before SaveChanges actually pushes the data up to the server. In this sample, I update the ModifiedDate field for Modified Customer entities, then I do the same for new ("Added") Customer Entities as well as create new default password data.

Namespace MyAssemblyNamespace

  Partial Public Class AWEntities

    Private Sub AWEntities_SavingChanges(ByVal sender As Object, ByVal e As System.EventArgs)  _
              Handles Me.SavingChanges

      'find all entities whose state is Modified so that I can 
      '
update the Customer's ModifiedDate property

      Dim changedEntities = _
      Me.ObjectStateManager.GetObjectStateEntries(EntityState.Modified)

      For Each stateEntryEntity In changedEntities
        If TypeOf stateEntryEntity.Entity Is Customer Then
          Dim cust As Customer = cType(stateEntryEntity.Entity,Customer)
          cust.ModifiedDate = Now  'update the ModifiedDate
        End If
      Next

      'make sure new entities get modifiedDate and non-nullable fields populated
      Dim addedEntities = _
      Me.ObjectStateManager.GetObjectStateEntries(EntityState.Added)
      For Each stateEntryEntity In addedEntities
        If TypeOf stateEntryEntity.Entity Is Customer Then
          Dim cust As Customer = cType(stateEntryEntity.Entity,Customer)
          cust.ModifiedDate = Now
          'password hash cannot be null
          'for demo purposes just put a default string in there
          cust.PasswordHash = MyCustomMethodtoHashStrings("
p@ssword")
          'customer table also needs salt for hash
          cust.PasswordSalt = MyCustomMethodtoCreateRandomSaltBytes()
        End If
      Next
    End Sub

  End Class
End Namespace

(7/14: adding the base of the C# partial class as a few people have asked...)

For C#, you need wire up the event handler which you can do when the OnContextCreated event is hit.

namespace MyAssemblyNamespace
{
    public partial class AWEntities
    {
        partial void OnContextCreated()
        {
            this.SavingChanges += new System.EventHandler(mySavingChanges);
        }


        public void mySavingChanges(object sender, System.EventArgs e)
        {
            //saving changes logic
        }

    }

}

Sunday, July 13, 2008 10:27:34 AM (Eastern Standard Time, UTC-05:00)  #     |  Comments [0]  | 
 Thursday, July 10, 2008

A few months ago, Brian Dawson gave us a look at a bunch of perf tests for querying with ADO.NET and Entity Framework.

I adapted and enhanced those tests for my session at TechEd and then added even more logic to them as I dug into performance for my book.

I thought I would share some of what I found. All of the timings here are only meant to demonstrate the performance relatively between the technologies. They are hardly scientific benchmarks. In my book I've called them "backyard benchmarks".

The first set of tests is similar to Brian's in that I merely query for all of the customers in the customer table of AdventureWorksLT. That's about 450.

However, thanks to some tips from Brad Sarsfield and Bruno Guardia Robles who do performance testing on the DP team, we added an extra loop of queries to "prime the pump" so to speak and get anything like metadata loading, query caching and well as SQL Server query caching out of the way.

Here are the average times comparing different ways of querying data.

Again, read these as relative to one another and nothing else.

perfa

The EntityClient query looks funny, as you'd expect it to be faster. When the query is more complex and the data is shaped, the EntityClient performs better than ObjectQuery which makes sense to me.

This is not using any query caching  or pre-compiled queries or other advantages. I actually do a ton of those tests in that particular book chapter though.

Note that Entity Client and Object Services cache compiled queries by default (you can turn this off) which is a little different than using Compiled Queries in LINQ but has similar effect. So by default, the two Entity SQL tests are benefiting from that but the LINQ to Entities is not. So I really should either create a compiled query for LINQ to Entities and LINQ to SQL or turn query caching off for the two Entity SQL tests, because that's not completely fair.On the other hand, these *are* the defaults.

But what I found really interesting were updates.

There are a lot of ways to update data with ADO.NET. I chose to use DataAdapters since calling DataAdapter.Update is relative to calling context.SaveChanges. Here I queried those same 450 or so customers, edited each one, added 10 new ones then updated the database. I also was sure to clear out the 10 new records from the database after each iteration of the tests was complete. I didn't happen to do any deletes in this test.

I also did one DataAdapter.Update using UpdateBatch, just to compare.

In all cases I am starting the stopwatch, performing the update, then stopping the stopwatch. These times are the average of my 100 iterations of each test.

perfb

That is not a typo next to LINQ to SQL. I have not dug into why this is so different, but I had been told that EF was much faster than LINQ to SQL for updates. I had to see for myself. Bruno says this looks about right, but he's going to double check my code to make sure I didn't do anything completely wacky. And if I did it wasn't intentional.

But I was also interested to see that Object Services was also faster than DataAdapter.

I'm not trying to make a point here...just an observation because I have never seen these comparisons made before.

For all of these methods there are a lot of things you can do to improve this performance, not only in code but on the servers. And some server tweaks might benefit one method but not another. These tests are just using all defaults and gives me a stake in the ground. Now if I didn't need to actually finish my book, I could just keep at it which would be fun and interesting. But it wouldn't be so fun when Tim O'Reilly comes knocking on my door wondering where the heck my book is!

Thursday, July 10, 2008 4:07:06 PM (Eastern Standard Time, UTC-05:00)  #     |  Comments [4]  | 
 Wednesday, July 09, 2008

At Remix 07, I got an intro to the fact that Robotics Studio has APIs in there that are being used for some amazing projects that have nothign to do with robots. Last month I had a chance to talk with the man who heads up the Robotics Division at Microsoft and then coincidentally discovered an article on the same in the June 2008 MSDN Mag. Read more...

[A New DevLife Post]

Wednesday, July 09, 2008 10:28:19 AM (Eastern Standard Time, UTC-05:00)  #     |  Comments [0]  | 
 Friday, July 04, 2008

I definitely want to hear Roger Jennings' story! Roger, your turn!! :-)

Friday, July 04, 2008 7:53:04 PM (Eastern Standard Time, UTC-05:00)  #     |  Comments [1]  | 
 Thursday, July 03, 2008

I've been called out by Shawn Wildermuth to answer a bunch of questions about how I got started in programming, etc. I've done that over here and called out 5 more folks as well.

[A New DevLife Post]

Thursday, July 03, 2008 2:50:24 PM (Eastern Standard Time, UTC-05:00)  #     |  Comments [0]  | 
 Sunday, June 29, 2008

Sorry, this has nothing to do with Entity Framework. :-)

This is about garden slugs! I've been having some problems with the slugs decimating the Romaine in my garden. Since my husband wouldn't let me use any of his fancy beer to lure them away, I used the next trick I learned about - "over ripe" yogurt.

I put it in a small yogurt container, dug a whole in the corner of my garden and placed the container in there so that the top was level with the ground.

Yesterday I went out there and it looked like every slug in Vermont had heard about the awesome yogurt being served up on Moody road. They were coming out of the tall grass surrounding the garden and I think there must have been 50 there.

Whoa - big mistake. Now all of those slugs know about my romaine! I probably should have put that yogurt a bit farther from the garden.  It's similar to when people very cleverly buy those "bag a bugs" to lure Japanese Beetles away from their flowers. But the scent in those sacks is so powerful that it draws Japanese Beetles from far away. We've trained our neighbors not to use them. So far so good this year - the roses are blooming and actually sticking around!

I went out this morning to take a picture of the slugs because it was so bizarre and was surprised to find they were all gone. It was like a big frat party had just dissipated and to add to the image, there were two slugs that were slowly slugging there way away from the yogurt container back into the weeds that surround the garden.

The real goal was that they were supposed to fall in there and drown (I know - murderer! All for a head of lettuce!) but instead they drained the yogurt and headed off. At least the mass of slugs wasn't attacking the lettuce. But I'm sure they'll be back!  EEEEEW.

Sunday, June 29, 2008 11:06:48 AM (Eastern Standard Time, UTC-05:00)  #     |  Comments [1]  |