Saturday, November 20, 2010

Creating Composite Keys using Code First with Entity Framework

Update: For Entity Framework 4.1 RTM, the exception message is a little bit different. It suggests to use the ColumnAttribute instead of DataMemberAttribute. At the time of EF CTP 4, the Column attribute did not exist yet, so they were temporary using the DataMember attribute. I have updated this post to use Column attribute as the latest EF version.

I am starting using the Entity Framework CTP 4, that includes code first approach with data annotations.
When creating composite primary keys, you need specify the order of the primary keys, otherwise you will get an exception similar to:
System.InvalidOperationException : Unable to determine composite primary key ordering for type 'PlaylistTrack'. Use the ColumnAttribute or the HasKey method to specify an order for composite primary keys.

As the exception message describes, one option is to use data annotations and add the Key and Column attributes to define the composite key as shown below:

public class PlaylistTrack
    {
        [Key, Column(Order=1)]
        public int PlaylistId { get; set; }

        [Key, Column(Order = 2)]
        public int TrackId { get; set; }

        [RelatedTo(ForeignKey = "PlaylistId")]
        public Playlist Playlist { get; set; }

        [RelatedTo(ForeignKey = "TrackId")]
        public Track Track { get; set; }
    }

Another option is to define the composite key using the HasKey method. In this option, the entity class will be:

public class PlaylistTrack
    {
        public int PlaylistId { get; set; }
        public int TrackId { get; set; }

        [RelatedTo(ForeignKey = "PlaylistId")]
        public Playlist Playlist { get; set; }

        [RelatedTo(ForeignKey = "TrackId")]
        public Track Track { get; set; }
    }

And the composite key is defined using the HasKey method when building the model:

var builder = new ModelBuilder();

    //...

    builder.Entity<PlaylistTrack>().HasKey(p=>new {p.PlaylistId, p.TrackId});

    //...

    model = builder.CreateModel();

My personal choice is to use data annotations which were introduced since EF4 CTP3.

Tuesday, November 16, 2010

Chinook Sample Database 1.3 Released

The Chinook Database is a sample database available for multiple database systems. It can be created by running a single SQL script. Chinook database is an alternative to the Northwind database, being ideal for demos and testing ORM tools targeting single and multiple database servers.


The Chinook Database represents a media store, including tables for artists, albums, media tracks, invoices and customers. The media information was generated from my iTunes library file, but anyone can download its source code and use their own iTunes library information. The sales information is auto-generated for a 4 years period. You can see the Chinook data model here.


This new version includes support for SQLite and EffiProz. EffiProz is a cross-platform embedded database written entirely in C#. Chinook database is available for:


  • EffiProz
  • MySQL
  • Oracle
  • SQL Server
  • SQL Server Compact
  • SQLite
You can download the latest release from here. There are available SQL scripts for each database system and also embedded database files for SQL Server Compact and SQLite.

Monday, September 20, 2010

How to Map Skydrive as a Network Drive in Windows 7

There are already many posts about mapping Skydrive as a network drive in Windows and you are wondering why I am creating a new one. The reason is very simple, none of these existing posts worked for me. So, I decided to put together all the information that worked for me, and hopefully it can help someone else with the same problem.

Check Your Windows Environment

The first step is to make sure your Windows environment is ready for this mapping. I am using Windows 7 x64, so I am not sure if this applies to other Windows versions, but it does not hurt to check.

1. WebClient Windows Service must be running as discussed here.

  • Open the Services management console (Start / Run / services.msc) and locate the WebClient service.
  • Start the WebClient service if it is stopped.
  • Open its Properties window, and set the Startup type to Automatic.
Note: Although this service was already running for me, I still had to restart it and set it to automatic startup in order to be able to map Skydrive.

2. Internet Explorer - LAN Settings should have Automatically detect settings unchecked
  • Open Internet Explorer.
  • Go to Tools, Internet Options.
  • Click on the Connections tab, and click on the LAN Settings.
  • Uncheck the Automatically detect settings.
Note: This might sound weird to check, but I also had to change this setting in order to make it work. When trying to map Skydrive using Windows Explorer, it was asking for my Windows Live credentials multiple times (about 3 times) until it fails.
    Determine the WebDAV access address

    The second step is to determine the proper address (WebDAV access address) you should use to connect to a Skydrive folder. You cannot directly use the URL shown in your browser since it does not work. You will need to get the WebDAV access address by using one of the following options:
    • Manually figure out the address based on the browser URL as described here. I do not recommend this method since the folder name might be different than the one seen on the browser. For example, here it mentions that "Documents" folder should be "^2Documents", but for me it was "^.Documents".
    • Use MS Office 2010 to save a document to Skydrive and then be able to see the WebDAV access address as described here. It would be a good option if you have this version of MS Office.
    • Build your own application that access http://docs.live.net/SkyDocsService.svc and query for the WebDAV folders. It is good to know about this WCF service, but it will take sometime to build a client application.
    • Use an existing application that uses the SkyDocsService and retrieve the information we need: http://skydrivesimpleviewer.codeplex.com/. This open source project provides a command prompt application dumpurls.exe and also a WPF application SkyDriveSimpleViewer.exe.
    I decided to use the simplest way, e.g. the dumpurls.exe command prompt application. Download dumpurls.exe, and run it from a Command Prompt window by passing your email (Windows Live or Hotmail) and your password. If you are not confident about passing your credentials to this application, you can temporary change your password in Windows Live before running this application, and restore it after.

    DumpUrls.exe me@hotmail.com p4ssw0rd
    

    The output is something like:

    https://zzzzzz.docs.live.net/yyyyyyyyyyyyyyyy/^.Documents
    https://xxxxxx.docs.live.net/yyyyyyyyyyyyyyyy/MyFolder
    

    You will not use these URLs directly, but the corresponding paths instead:

    \\zzzzzz.docs.live.net@SSL\yyyyyyyyyyyyyyyy\^.Documents
    \\xxxxxx.docs.live.net@SSL\yyyyyyyyyyyyyyyy\MyFolder
    

    Map Skydrive as Network Drive

    Although you can map it by using Windows Explorer, I mapped using a single command line in the Command Prompt window. So, open a Command Prompt window and run the following command to map a folder named MyFolder to the drive Z by using your credentials:

    net use Z: "\\xxxxxx.docs.live.net@SSL\yyyyyyyyyyyyyyyy\MyFolder" /user:me@hotmail.com p4ssw0rd /persistent:yes
    

    The expected output is:
    The command completed successfully.
    

    Note: these are the errors I had before I fixed my Windows environment as explained in the beginning of this article:
    • System error 5 has occurred: the solution for me was to change the IE setting described above.
    • System error 1920 has occurred: the solution was to restart the WebClient service as described above.
    Now, you can just open Windows Explorer and start using your new drive on the cloud. I noticed that Windows Explorer does not report the proper used and free space, it might show that you have more than 25GB available.

      Saturday, September 18, 2010

      Microsoft ASP.NET Security Vulnerability: The 'Padding Oracle' Attack

      Early this week, a couple of security researchers, Juliano Rizzo and Thai Duong, have implemented an attack that exploits the way ASP.NET applications handle encrypted session cookies (see more details here). They have discussed this in detail during the Ekoparty conference in Argentina. Their research paper is Practical Padding Oracle Attacks.

      In the context of cryptography, an oracle is a system that provides hints as you ask it questions. And this attack explores a vulnerability in ASP.NET which acts as a padding oracle. This vulnerability is explained in details in Understanding the ASP.NET Vulnerability.

      This vulnerability allows attackers to have access to decrypt the information stored in the ViewState object. If sensitive information is stored there, such as passwords or database connection strings, then this data is compromised. If an ASP.NET application is using ASP.NET 3.5 SP1 or above, the attacker could use this encryption vulnerability to request the contents of an arbitrary file which the worker process has access to, for example, the web.config file.

      Microsoft has released a security advisory about the problem: Microsoft Security Advisory (2416728). If you or your clients have ASP.NET Web sites, then you must apply the necessary changes as described here: Scott Guthrie: ASP.NET Security Vulnerability

      Update: Also take a look at Scott Guthrie's FAQ about AS.NET Security Vulnerability.

      Monday, June 14, 2010

      JavaScript syntax error with telerik.grid.min.js

      When implementing custom binding with the Telerik ASP.NET MVC, I based my code on this example described here under the Controller tab.

      The CustomBinding action is called when the whole page is loaded or refreshed, then showing on the grid the default data, e.g. the first page. This action should return a view with the model object (IEnumerable<Order> in this example).

      The _CustomBinding action is called from an AJAX call when the user clicks on the grid controls, like page number, sort, or filter. This action should return a view with a GridModel object and not with the view model (IEnumerable<Order>). If you do not use a GridModel object, then you will get the JavaScript syntax error char 4048 in telerik.grid.min.js.




      Although the Telerik example is right, when I wrote my code based on it, I mistakenly used the wrong model object, and couldn't figure out what was wrong. Thanks for this forum post that enlighted me of what was going on.

      Saturday, June 12, 2010

      Using SyntaxHighlighter (version 2.1.364) with Blogger

      After spending sometime to make SyntaxHighlighter work with Blogger, I finally found an article that has the solution that perfectly worked for me. The other posts I found were not using the latest version (version 2.1.364 when this post was published), so no support for latest languages such as PowerShell, or they were using the latest version but the instructions didn't work 100%.The following article worked for me:

      Wednesday, June 09, 2010

      Checking the type and size of RAM with Windows PowerShell

      I subscribe to the PowerTip of the day email of PowerShell.com and I got this tip today. If you want to know the type and size of RAM your PC uses, and available banks, you can use the following script:

      $memorytype = "Unknown", "Other", "DRAM", "Synchronous DRAM", "Cache DRAM",
      "EDO", "EDRAM", "VRAM", "SRAM", "RAM", "ROM", "Flash", "EEPROM", "FEPROM",
      "EPROM", "CDRAM", "3DRAM", "SDRAM", "SGRAM", "RDRAM", "DDR", "DDR-2"
      $formfactor = "Unknown", "Other", "SIP", "DIP", "ZIP", "SOJ", "Proprietary",
      "SIMM", "DIMM", "TSOP", "PGA", "RIMM", "SODIMM", "SRIMM", "SMD", "SSMP",
      "QFP", "TQFP", "SOIC", "LCC", "PLCC", "BGA", "FPBGA", "LGA"
      $col1 = @{Name='Size (GB)'; Expression={ $_.Capacity/1GB } }
      $col2 = @{Name='Form Factor'; Expression={$formfactor[$_.FormFactor]} }
      $col3 = @{Name='Memory Type'; Expression={ $memorytype[$_.MemoryType] } }
      
      Get-WmiObject Win32_PhysicalMemory | Select-Object BankLabel, $col1, $col2, $col3
      
      

      The output would be something like:

      BankLabel                     Size (GB) Form Factor         Memory Type
      ---------                     --------- -----------         -----------
                                            2 DIMM                DDR-2
                                            2 DIMM                DDR-2
                                            2 DIMM                DDR-2
                                            2 DIMM                DDR-2
      

      It works pretty nice, doesn't it?

      Monday, May 24, 2010

      MVC Music Store and Chinook Database

      The MVC Music Store is a sample application built on ASP.NET MVC Framework 2. It includes the source code and a tutorial explaining the steps to build it. This is a great tutorial if you want to get started on ASP.NET MVC 2. When I looked at the documentation, I noticed that the data used by the application is very familiar. Jon Galloway, the author, mentioned on this post that the MVC Music Store data is based on the Chinook Database. The Chinook Database was built using my iTunes library as sample data, and that is why I recognized some particular artists and albums: a mix of rock, heavy metal, classical music and Brazilian music.
      As to the Chinook Database I have a list of improvements to be done and need to get sometime to work on a new release. I am also thinking about adding support to document-oriented databases such as Raven DB and MongoDB.