Saturday, December 8, 2012

Recreating a Dropped Database in Entity 5

I've been working on a windows service that constantly monitors a local database. One of the responsibilities of the service is to create and seed the database if it doesn't already exist. This was necessary because the database may be dropped at anytime within the system, and it needs to be recreated quickly. With Entity Framework 4.3 and no migration support, the following code achieved that.

if (!context.Database.Exists())
{
    context.Database.Create();
    _Seed(context);
    context.SaveChanges();
}

New specifications for this system required support database migrations, so I took the opportunity to upgrade the code to use Entity Framework 5. Without going into the details of how EF 5 migrations work, I'll just say that I enabled migrations and I'm now using the Configuration class to handle seeding by overriding the Seed(context) method.

To handle the migrations, I opted to use the MigrateDatabaseToLatestVersion initializer provided in the framework. This initializer executes any missing migrations to get the database current.

Entity.Database.SetInitializer<DatabaseContext>(
    new MigrateDatabaseToLatestVersion<DatabaseContext, Migrations.Configuration>());

After these changes, I simplified the database check and creation process to the following

if (!context.Database.Exists())
{
    context.Database.Initialize(true);
}

What I found was this works fine when no database exists and the service is started, but it no longer works properly when the database is dropped during the runtime of the service. The Exists check properly returns false, but the Initialize method call does not actually create the database. I'm passing true as the argument, which should force the initializer to run. So what's going on here? From what I can tell, the instance of MigrateDatabaseToLatestVersion will only create a database once. To work around this, I create a new instance of the initializer whenever the database doesn't exist.

if (!context.Database.Exists())
{
    Entity.Database.SetInitializer<Database.DatabaseContext>(
        new MigrateDatabaseToLatestVersion<Database.DatabaseContext, Migrations.Configuration>());
    context.Database.Initialize(true);
}
else
{
    context.Database.Initialize(false);
}

The database is now properly recreated when it no longer exists.

Tuesday, November 6, 2012

Entity Framework 5 requires NuGet 2

After upgrading to Entity Framework 5, the Enable-Migrations command starting failing. I had used it with EF 4.3, but now I kept getting the following error when running Enable-Migrations in the Package Manager Console:

The EntityFramework package manager is not installed on project 'MigrationTest'.

But why? I clearly had EF5 installed, and I wasn't getting any build time errors. What's the problem? Well, after a lot of searching and research, I happened to read that EF 5 is only compatible with NuGet 2. I checked on the version I had installed, and sure enough, I was running NuGet 1.7. After upgrading to the most current version of NuGet, Enable-Migrations started working again.

I have two major issues with this.

  1. Why not a more clear error message? Telling me the package wasn't installed sent me off in the wrong direction.
  2. Why doesn't the Entity Framework Development Center state this information in the 'Get Entity Framework' section? There is no mention of EF 5 being incompatible with older versions of NuGet. Thanks guys.
In any case, if you find yourself upgraded Entity, don't forget to keep NuGet up to date as well.


Friday, October 19, 2012

Intel SDK for OpenCL Fails to Create New Projects

I recently began working with OpenCL and opted to use Intel's OpenCL SDK. I'm working in a Windows environment with Visual Studio 2010, so I was drawn to Intel's SDK because of their Visual Studio plugin support. Unfortunately, I didn't get very far before I hit the first snag.

After installing the SDK, the following project template is available.
OpenCL projects are available after installing the SDK
I gave my project a name and clicked 'OK', and I ended up with an empty project. It had the name I gave it, but no files were associated with it. There was nothing to work with. I tried several more times to no avail. All I got were empty projects. After some time on Intel's forums, I found the culprit. There is a small bug in the current SDK, and it causes project creation on Visual Studio 2010 to fail. Luckly, it's an easy fit.

To get projects to create properly, navigate to the Visual Studio directory. From there, go to VC\vcprojects\OpenCL and locate the  OpenCLProj.vsz file. Open this file in a text editor and replace Wizard=VsWizard.VsWizardEngine.9.0 with Wizard=VsWizard.VsWizardEngine.10.0.

That's it! OpenCL projects are now created with the proper content.

Source: http://software.intel.com/en-us/forums/topic/278415

Monday, October 15, 2012

Extending XamDockManager to Include a New Tab Button

The Infragistics XamDockManager provides an MDI style interface that mirrors Visual Studio 2010, complete with panes that can be floated, docked, and tabbed. One feature not found in XamDockManager but common in MDI tabbed applications is a new tab button. For example, most modern web browsers include this button to the left of the tab headers. I recently found myself needing this feature to meet software requirements that were added to a project I had already begun. With my entire UI already built on XamDockManager, I frantically searched the documentation for the some hidden ability to expose this button, but I came up empty. But all was not lost. The power and flexibility of WPF came through, and I was able to add the button myself.

Any developer that has used WPF knows that the heart of technology lies in styles and templates. The Infragistics implementation is no different, and they rely on it heavily to achieve theming. Why does this matter to me? One reason. All of these templates and styles are provided to the developers and can be found in the install directory. For example, mine are located in "C:\Program Files (x86)\Infragistics\NetAdvantage 2012.1\WPF\DefaultStyles". With these tools in hand, customization can begin.

Below is my basic implementation of the XamDockManager with MDI tabs.

<igDock:XamDockManager Name="dockManager">
    <igDock:DocumentContentHost>
        <igDock:SplitPane>
            <igDock:TabGroupPane Name="tabsPane" TabStripPlacement="Top">
                <igDock:ContentPane Header="Tab 1" />
            </igDock:TabGroupPane>
        </igDock:SplitPane>
    </igDock:DocumentContentHost>
</igDock:XamDockManager>

The TabGroupPane is the item to focus on. It's the control that provides the reserved space for tab headers and the list/close buttons. The ControlTemplate for TabGroupPane can be found in the directory mentioned above, located in \DockManger\DockManagerGeneric.xaml.
<ControlTemplate x:Key="{x:Static igDock:TabGroupPane.DocumentTabGroupTemplateKey}" TargetType="{x:Type igDock:TabGroupPane}">
  <DockPanel ClipToBounds="True" SnapsToDevicePixels="True" KeyboardNavigation.TabNavigation="Local">
   <DockPanel x:Name="PART_HeaderArea" Panel.ZIndex="1" DockPanel.Dock="{TemplateBinding TabStripPlacement}">
    <DockPanel>
     <Button x:Name="closeBtn"
       DockPanel.Dock="Right"
       Command="{x:Static igDock:TabGroupPane.CloseSelectedItemCommand}"
       Style="{DynamicResource {x:Static igDock:TabGroupPane.DocumentCloseButtonStyleKey}}" 
       />
     <Menu x:Name="filesMenu" DockPanel.Dock="Right" Style="{StaticResource RootMenuStyle}">
      <MenuItem x:Name="PART_FilesMenuItem"
                            Style="{DynamicResource {x:Static igDock:TabGroupPane.DocumentFilesMenuItemStyleKey}}" />
     </Menu>
                    <!-- AS 9/10/09 TFS19267 - Added CommandParameter -->
     <Button x:Name="showNavigatorButton"
                            DockPanel.Dock="Right"
                            Visibility="Collapsed"
                            Command="{x:Static igDock:DockManagerCommands.ShowPaneNavigator}" 
                            CommandParameter="{TemplateBinding igDock:XamDockManager.DockManager}"
       Style="{DynamicResource {x:Static igDock:TabGroupPane.DocumentPaneNavigatorButtonStyleKey}}" 
                            />
     <ItemsPresenter x:Name="PART_TabHeaderPanel" Margin="5,2,10,0"
                  KeyboardNavigation.TabIndex="1"/>
    </DockPanel>
   </DockPanel>
   <Border x:Name="ContentPanel"
                KeyboardNavigation.TabIndex="2"
                KeyboardNavigation.TabNavigation="Local"
                KeyboardNavigation.DirectionalNavigation="Contained"
                BorderThickness="{TemplateBinding BorderThickness}"
                CornerRadius="3"
                BorderBrush="{DynamicResource {x:Static igDock:DockManagerBrushKeys.TabbedPaneOuterBorderFillKey}}"
                Background="{TemplateBinding Background}"
                Visibility="Visible"
                SnapsToDevicePixels="True" >
    <Border x:Name="InnerBorder"
                        BorderThickness="1"
                        CornerRadius="1"
                        BorderBrush="{DynamicResource {x:Static igDock:DockManagerBrushKeys.TabbedPaneInnerBorderFillKey}}"
                        SnapsToDevicePixels="True" >
     <Border borderbrush="{DynamicResource {x:Static igDock:DockManagerBrushKeys.TabbedPaneCenterFillKey}}" borderthickness="2" snapstodevicepixels="True" x:name="ThickInnerBorder">
      <Border background="{TemplateBinding Background}" borderbrush="{DynamicResource {x:Static igDock:DockManagerBrushKeys.TabbedPaneOuterBorderFillKey}}" borderthickness="1" snapstodevicepixels="True" x:name="InnerMostBorder">
       <ContentPresenter ContentSource="SelectedContent"
                                 Margin="{TemplateBinding Padding}"
                                 x:Name="PART_SelectedContentHost"
                                 SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                 ContentTemplateSelector="{TemplateBinding SelectedContentTemplateSelector}"
                                 ContentTemplate="{TemplateBinding SelectedContentTemplate}"
                                 Content="{TemplateBinding SelectedContent}" />
      </Border>
     </Border>
    </Border>
   </Border>
  </DockPanel>
</ControlTemplate>
Note that I've omitted the triggers for simplicity. The area to focus on is lines 3-25, where the tab header layout is defined. A DockPanel is used to add the close and menu buttons that appear in the right corner of the control. This is where the new tab button can be added. To add the button, the following line should be added as the last item in the DockManager.
<Button DockPanel.Dock="Left" Style="{StaticResource NewTabButtonStyle}" />
That's all it takes. The new tab button now lines up to the right of the right-most tab header.
New tab button
Looks good, right? Well, it's getting there, but there is a problem I ran across with this layout. The new button is chosen as the victim to lose units when the measurement pass determines not everything will fit, giving the following results when there is little space or a lot of tab headers.

Squashed new tab button
That looks terrible, but there is an easy fix. The layout needs to be modified so that the new tab button will not be resizable. To achieve this, I wrapped the ItemsPresenter together with the button in a seperate DockPanel nested within the original DockPanel. Docking the DockPanel to the left of the parent DockPanel will prevent the items within from being resizable and getting squashed, while keeping them aligned to the left of the control.
<DockPanel DockPanel.Dock="Left" HorizontalAlignment="Left">
    <Button DockPanel.Dock="Left" Style="{StaticResource NewTabButtonStyle}" />
    <ItemsPresenter x:Name="PART_TabHeaderPanel" Margin="5,2,10,0"
                               KeyboardNavigation.TabIndex="1" DockPanel.Dock="Left" />
</DockPanel>

Now that the layout is working, it's time to address the look and feel of the new tab button. The style referenced, NewTabButtonStyle, is a button style I created for the look and feel I wanted. You can get creative here with the design of the button, but I'd recommend at least using the Infragistics brushes in the style. This keeps the coloring consistent if the theme is changed. For example, I used the following keys for coloring.

  • igDock:DockManagerBrushKeys.TabbedDocumentNotActiveOuterBorderFillKey
  • igDock:DockManagerBrushKeys.TabbedDocumentNotActiveCenterFillKey
  • igDock:DockManagerBrushKeys.TabbedDocumentHottrackCenterFillKey
By using these keys, the new tab button changes colors automatically when the theme of the XamDockManager is changed.
That wraps it up. With these minor modifications and additions, I was able to add a core piece of functionality for my application. A win for both WPF and Infragistics.

Source code: XamDockManager.NewTabButton