How to Make Tracing and Caching Providers Work for EF 4.1 Code First

Posted by Hugh Ang at 12/21/2011 09:08:00 PM

The tracing and caching providers (or here) provide an excellent way to trace and cache EF queries. Unlike those that attempt to do the same above the EF API, these providers work under the covers and make tracing and caching non-invasive for the application code. Specifically, for cases where entities are lazy-loaded via EF and those entities are to be cached, this caching provider is truly more advantageous.

However, these providers were written before EF 4.1 code first and they wouldn't work if you just follow the old sample. Luckily, it is not too difficult to make them work. The trick is to create a wrapping EFCachingConnection or EFTracingConnection that wraps a DbConnection (such as SqlConnection) and pass it to the DbContext constructor. I will just demonstrate the caching related code here but you should be able to chain tracing, caching and then the underlying SqlConnection using the same pattern.

First, a minor modification to the EFCachingConnection constructor is needed. As shown in the following code, we need to be able to set the wrappedProviderInvariantName via the ctor:




  1.  

  2. public EFCachingConnection(DbConnection wrappedConnection, string wrappedProviderInvariantName)

  3. {

  4. this.WrappedConnection = wrappedConnection;

  5. this.CachingPolicy = EFCachingProviderConfiguration.DefaultCachingPolicy;

  6. this.Cache = EFCachingProviderConfiguration.DefaultCache;

  7. base.wrappedProviderInvariantName = wrappedProviderInvariantName; // make it possible to set the wrappedProviderInvariantName via this ctor

  8. }





The I use the following helper function to create an instance of the EFCachingConnection that wraps a SqlConnection:




  1.  

  2. public static EFCachingConnection CreateEFCachingConnectionWrapper(string nameOrConnectionString)

  3. {

  4. string connectionString;

  5. if (nameOrConnectionString.Contains("="))

  6. connectionString = nameOrConnectionString;

  7. else

  8. connectionString = ConfigurationManager.ConnectionStrings[nameOrConnectionString].ConnectionString;


  9. DbConnection connection = new SqlConnection(connectionString);

  10.  

  11. return new EFCachingConnection(connection, "System.Data.SqlClient");

  12. }





Now you would simply pass the newly constucted EFCachingConnection instance to the ctor of DbContext:




  1.  

  2. public MyContext(DbConnection connection)

  3. : base(connection, true)

  4. {





Note that MyContext is the application's EF code first context, which derives from DbContext and has probably overriden the OnModelCreating() method.

Last and not the least you would need to call EFCachingProviderConfiguration.RegisterProvider() first when you start your application.

Happy holidays and happy EF coding!

Recording VS.NET Web Performance Test for Flex

Posted by Hugh Ang at 3/01/2011 02:36:00 PM

We are building a web application that integrates with a third party software by embedding their Flex objects in our ASPX pages. When we started using VS.NET 2010 Web Performance Test, everything worked fine except for the weborb requests made by the Flex objects to the server. Basically, the requests recorded by the web test, when played back and sent to the server, were causing the server to respond with errors. From googling, it looks like that the same issue has been experienced by other folks as well. At this point, it would be easy to simply dismiss VS.NET 2010 Web Performance Test as a viable tool for Flex. What a costly mistake this would have been if we had stopped doing more analysis!

Looking at the initially recorded tests, I found out that all the data posted by the Flex objects was recorded and played back as string data type. Examining the payload in Fiddler, however, showed that the data is obviously binary. So our recorded test was sending the data with lost fidelity and the server just choked.

Thinking that there must be configuration to tweak to make our tests record binary data, I started searching MSDN for documentation. Sure enough, I found this link. I went ahead and added "application/x-amf" as the content type. Then I recorded the test again and ran the scripts.

Voila, everything worked like a charm!

Fixing My Custom Built PC After a Power Outage

Posted by Hugh Ang at 5/10/2010 10:09:00 PM

I usually wouldn't blog about hardware but since this experience felt just like debugging a software problem, here it goes:

The NJ area experienced a pretty bad wind storm this past weekend. Downed tree branches knocked out some power lines, which caused scattered power outages in the area. My house was one of the unlucky ones that were hit with the outage. After the power came back in the next morning, one of my desktop PCs that I built several years ago wouldn't start. This is the PC that I have just recently upgraded from Vista to Windows 7 and I also built inside the host PC a VPC with VS.NET 2010 and all the other latest cool stuff (Silverlight, etc.). So I was determined to figure out what went bad and hoped to salvage as much as possible.

The symptom of the problem is that initially it wouldn't even turn on when I pressed the power button. After I switched to a different circuit in the house, it could start with fans and lights on. So it was evident that the PSU was still good. But there was no display on the monitor and no system start beep sound either. What was even worse was I could smell burning plastic. Some board was fried during the outage and now with the power on, sending the current through the board is still burning it.

I turned off the power and began visually inspecting the mobo, hoping to find where the burn was but to no avail. I started disconnecting the IDE cable to the DVD rom, SATA cables to the HDD, unplugging RAM. I would make one change at a time while powering on to see if there is a system beep. Nothing so far.

The last item was the video card with dual DVI interfaces for my two monitors. After I unplugged the video card, bingo! the system started making beeping sounds. And as I flipped the video card over, sure enough I found the burning spot, which I wouldn't have been able to see when it was installed closely to the bottom of the tower in the facing down position. Fortunately I had a spare video card. After plugging that in I had no problem booting into Windows 7. It did require resetting the resolution after automatically installing the driver for the card. Minutes later, I noticed that automatic Windows update was complaining about not able to complete the updates and a closer look revealed that the system clock was set to 1/1/2006. I suspect this was done as I was resetting the BIOS during the diagnosis process - while the power cord was unplugged, I pressed and held the power button for a few moments.

So fortunately it was only a small loss instead of the MOBO/CPU that are commonly getting fried during power outages. One thing I will be doing for sure going forward is to use the battery backup surge protector as opposed to a low end one I was using :-)

Application Migration - Vista/Win7 Compatibility

Posted by Hugh Ang at 12/16/2009 01:07:00 AM

It has been a while since the last time I blogged. The theme of my work for the last 4 months or so is really migration, migration, and migration!


  • First I helped our team with a VB6 to VB.NET migration project that ran into some sticky interop problems.

  • Secondly I worked as an advisor for a customer who was in the process of migrating their apps from Win2K to Vista. Please don't ask me why they chose to go to Vista while Win7 was coming out - it was a decision already rationalized by the management when I was brought in.

  • And lastly, just a couple of weeks ago, I helped Microsoft deliver a Win7 training course for a customer who is looking to migrate to Win7 in the next 6 months. Although it is not unusual that I present in a conference room or mentor developers privately, this was actually my first time to do a formal training. The sessions were recorded and are being made available for later reuse by the customer. Speaking of the sessions on tape, I actually saw Oliver Stone and Michael Douglas when they were shooting Wall Street 2 on site at the Borders book store at the corner of Wall Street and Broadway. And that was when I was working on the Vista migration mentioned above.



Enough with the chronology and my celebrity sightings. As the title suggests, I'd like to cover the most common compatibility issues for Vista/Win7from a developer perspective. So here are the two top issues I have seen so far:


  • Writing to %ProgramFiles% (e.g. C:\Program Files) and %SystemRoot% (e.g. C:\Windows) locations

  • Writing to registry hive: HKLM\Software



It is quite common that legacy apps write configuration data to the above locations. But with UAC enabled in Vista/Win7, an admin user will be running an app with standard user privileges unless the app has a manifest explicitly requesting admin privilege or the app is started with "Run as administrator" context menu; And since standard user will only have read/execute rights to those locations, the attempt made by those apps to write configuration data to those locations will fail. Using the icacls at the command prompt shows the ACL of %ProgramFiles% as in the following on my machine:


C:\Program Files>icacls .
. NT SERVICE\TrustedInstaller:(F)
NT SERVICE\TrustedInstaller:(CI)(IO)(F)
NT AUTHORITY\SYSTEM:(M)
NT AUTHORITY\SYSTEM:(OI)(CI)(IO)(F)
BUILTIN\Administrators:(M)
BUILTIN\Administrators:(OI)(CI)(IO)(F)
BUILTIN\Users:(RX)
BUILTIN\Users:(OI)(CI)(IO)(GR,GE)
CREATOR OWNER:(OI)(CI)(IO)(F)


There is an additional twist here. The app may not be failing but you will not see files or registry keys written to the intended location. This is the work of data redirection(or UAC virtualization). The details can be found here. But basically:


  • Writing to %ProgramFiles%\MyApp\myapp.ini gets redirected to C:\Users\Username\AppData\Local\VirtualStore\Program Files\MyApp\myapp.ini

  • Writing to HKLM\Software\MyApp\ gets redirected to HKCU\Software\Classes\VirtualStore\MACHINE\Software\MyApp



When virtualization happens, you can fire up Process Monitor and notice a REPARSE event, followed by writing to those redirected locations.

As the redirection is on per-user basis, this can mess up the intended behavior of the application. For example, the application may be intended to be used by multiple users on one machine and the configuration data should be shared. Microsoft is making no guarantee that the virtualization will be in future Windows. So what to do as a developer? The best practice for writing per machine configuration data is using %ProgramData% (e.g. C:\ProgramData). For per user configuration data, use %LocalAppData% (e.g. C:\Users\User\AppData\Local) for local or %AppData% for roaming user profile.

Running icacls on %ProgramData% shows that a standard user would have additional AD(append data/add subdirectory), WD(write data/add file), WEA(write extended attributes) and WA(write attributes) privileges:


C:\ProgramData>icacls .
. NT AUTHORITY\SYSTEM:(OI)(CI)(F)
BUILTIN\Administrators:(OI)(CI)(F)
CREATOR OWNER:(OI)(CI)(IO)(F)
BUILTIN\Users:(OI)(CI)(RX)
BUILTIN\Users:(CI)(WD,AD,WEA,WA)


And lastly, don't hard code any of the paths we have talked about. There are well-known APIs to get them. In .NET, follow this sample:



string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);


 


path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);


 


path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);




And if you write C++ code, here is a sample:



void ShowFolders(HWND hWnd)


{   


    LPWSTR wszPath = NULL;


    HRESULT hr = SHGetKnownFolderPath(FOLDERID_ProgramData, KF_FLAG_NO_ALIAS | KF_FLAG_DONT_VERIFY, NULL, &wszPath);


    if ( SUCCEEDED(hr) )


    {


        // work with wszPath


 


        CoTaskMemFree(wszPath);


    }


 


    hr = SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_NO_ALIAS | KF_FLAG_DONT_VERIFY, NULL, &wszPath);


    if ( SUCCEEDED(hr) )


    {


        // work with wszPath       


 


        CoTaskMemFree(wszPath);


    }


 


    hr = SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_NO_ALIAS | KF_FLAG_DONT_VERIFY, NULL, &wszPath);


    if ( SUCCEEDED(hr) )


    {


        // work with wszPath   


 


        CoTaskMemFree(wszPath);


    }


}


Hotfix KB971030 Released

Posted by Hugh Ang at 9/02/2009 04:58:00 PM

You can finally download this hotfix from here and the detailed information is available here. According to the information posted there, it is a fix for an access violation problem when making virtual function calls to the IList<T>, IEnumerable<T>, or ICollection<T> interface. I am not sure yet if this is another manifestation of the same dispatch token problem I described in my previous blog or the CLR team simply bundled together several virtual dispatch bug fixes that just include what I found.

I ran the same test harness that I used before and confirmed that the hotfix does indeed resolve the problem.

I was having some trouble installing the hotfix today but eventually got it installed. It turned out that my OS was Vista SP1 and I had to upgrade it to SP2 in order to install the hotfix. If you have another OS and wondering about the same question as Chris Dion had, the hotfix should be applicable to Windows Server 2000, Windows Server 2003, Windows Server 2008 and Windows XP.

CLR Virtual Call Stub Issue Resolved

Posted by Hugh Ang at 5/15/2009 01:51:00 PM

Good news - I have just received words from the Microsoft CLR team that the issue I detailed in this blog has been fixed in an upcoming QFE, which will be available for download through the Support/KB site using KB971030 in about a week. This also means that the fix will be automatically included in any future 3.5 service pack release. In addition, this has been fixed in the upcoming 4.0 release. I will try the fix in a week and keep everyone posted.

Making Assumptions in Application Design

Posted by Hugh Ang at 2/18/2009 11:46:00 AM

Back during the holidays, I wrote a small .NET program to manipulate my Canon XTi camera, which was connected to the PC via USB. Everything worked great when I was using my laptop that had Vista on it. But on my wife's laptop that had XP, the performance became unbearable. My utility program would wait for several minutes before I could start using it. The program's thread was pretty much idle during the waiting so I was asking myself: could this be the PC hardware? I tested this program on one of my desktops that also had XP. Nope, still the same poor performance. I then updated the camera's firmware and that didn't resolve the issue either. I began to suspect that this was OS related. Sure enough, when I plugged in the camera without my program running, XP took a much longer time than Vista to come up with the camera and scanners wizard. I noticed that while XP seemed to be cluelessly waiting, the CF card indicator light of the camera was flashing madly. I realized that XP was probably trying to download pictures from the camera, which was busy reading from the CF card. At the time, I had about 300 high resolution pictures on the 2GB CF card. After I switched it with an empty CF card, the performance problem just went away.

The morale of the story is that we need to be extra careful when making assumptions for users when designing UI applications. In this case, XP made a not necessarily wise assumption about the intention of plugging a camera into the USB port. Even for users who do want to download pictures this way, there is no visual clue provided, leaving users wonder what is going on.