Entity Framework 4.0 and Multiple Data Contexts

In the EF version 1.0, there was a problem when one would try to update multiple contexts as part of a single transaction.  For example, I can use Transaction Scope, the update one context, then second context.  Here is sample code to illustrate:

 

using (TransactionScope scope = new TransactionScope())
{
    try
    {
        using (RolodexEntities context = new RolodexEntities())
        {
            context.Connection.Open();

            Company company = new Company();
            company.CompanyName = "Test 1";
            company.DateAdded = DateTime.Today;
            context.AddToCompanies(company);
            context.SaveChanges();

            using (RolodexEntities context2 = new RolodexEntities(context.Connection as EntityConnection))
            {
                Company company2 = new Company();
                company2.CompanyName = "Test 1";
                company2.DateAdded = DateTime.Today;
                context2.AddToCompanies(company2);
                context2.SaveChanges();
            }
        }

        scope.Complete();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

This code in version 1.0 would throw an exception when second context’s constructor was called.  The exception was quite obscure and was referring to the fact that the connection was already open.  This was actually correct, but that was the whole reason I was passing in the connection.  I was trying to make sure that my transaction would not get propagated to Distributed Transactions Coordinator.  The transaction would always get promoted as soon as there are multiple SQL Server connections used within using scope/.end using scope code block.  So, in version 1.0 MSDTC would be required in the code above.

This issues was solved in version 4.0 (or 2.0 whichever you prefer).  Now your transaction can span multiple contexts without having to use DTC.  I think this is a great improvement because most large applications at some point or another will use multiple contexts.  This is one more reason why I am really excited about EF 4.0.  Number one reason by far is that you can now have foreign key IDs in addition to navigation properties.  This greatly simplifies your EF code in N-Tier environment.

Please feel free to ask any questions on this subject.

Silverlight, MVVM and Animations

Yesterday I was asked about a way to play animations in MVVM environment.

So, I gave this some thought today, and came up with a few ideas.

First, and the easiest way is to separate ViewModel from animation by attaching an animation to a behavior.  Here is how we would write the behavior:

public class MVVMSimpleAnimationBehavior : TargetedTriggerAction<UIElement>

{

    protected override void Invoke(object parameter)

    {

        RunAnimation();

    }

 

    public Storyboard AnimationStoryBoard

    {

        get { return (Storyboard)GetValue(AnimationStoryBoardProperty); }

        set { SetValue(AnimationStoryBoardProperty, value); }

    }

 

    public static readonly DependencyProperty AnimationStoryBoardProperty =

        DependencyProperty.Register("AnimationStoryBoard", typeof(Storyboard), typeof(MVVMSimpleAnimationBehavior), new PropertyMetadata(null));

 

 

    private void RunAnimation()

    {

        if (AnimationStoryBoard != null)

        {

            AnimationStoryBoard.Begin();

        }

    }

}

 

Pretty simple approach.  Here is how would use animation in the XAML:

<Button Content="Behavior Test" Grid.Column="1">

    <i:Interaction.Triggers>

        <i:EventTrigger EventName="Click">

            <local:MVVMAnimationBehavior AnimationStoryBoard="{StaticResource TestStoryboard}"/>

        </i:EventTrigger>

    </i:Interaction.Triggers>

</Button>

Now, I want to complicate the story a little bit.  I really want to trigger an animation in the UI via an event in my model.  I am going to start with a sample ViewModel.  I want to have an event there that I will later use as a trigger for my animation.  Here is what my ViewModel would look like:

public class SampleModel: INotifyPropertyChanged

{

 

    public event EventHandler StartAnimation;

 

    protected virtual void OnStartAnimation()

    {

        if (StartAnimation != null)

        {

            StartAnimation(this, EventArgs.Empty);

        }

    }

 

    public void RaiseEvent()

    {

        OnStartAnimation();

    }

 

    #region INotifyPropertyChanged Members

 

    public event PropertyChangedEventHandler PropertyChanged;

 

    protected virtual void OnPropertyChanged(string propertyName)

    {

        if (PropertyChanged != null)

        {

            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

        }

    }

 

    #endregion

}

My event is called StartAnimation.  Now it is time to develop a more complicate behavior to support my event driven animation from ViewModel.  I am going to actually combine new functionality with the simple behavior about and have multi-functional useful object.  Here is what the final product looks like:

using System;

using System.Windows.Interactivity;

using System.Windows;

using System.Windows.Media.Animation;

using System.ComponentModel;

using System.Reflection;

 

 

namespace SLMVVMAnimationBehavior

{

    public class MVVMAnimationBehavior : TargetedTriggerAction<UIElement>

    {

        private EventInfo info;

        protected override void Invoke(object parameter)

        {

            RunAnimation(this, EventArgs.Empty);

        }

 

        public Storyboard AnimationStoryBoard

        {

            get { return (Storyboard)GetValue(AnimationStoryBoardProperty); }

            set { SetValue(AnimationStoryBoardProperty, value); }

        }

 

        public static readonly DependencyProperty AnimationStoryBoardProperty =

            DependencyProperty.Register("AnimationStoryBoard", typeof(Storyboard), typeof(MVVMAnimationBehavior), new PropertyMetadata(null));

 

        public string EventName

        {

            get { return (string)GetValue(EventNameProperty); }

            set { SetValue(EventNameProperty, value); }

        }

 

        public static readonly DependencyProperty EventNameProperty =

            DependencyProperty.Register("EventName", typeof(string), typeof(MVVMAnimationBehavior), new PropertyMetadata(HandlModelChanged));

 

 

        public object Model

        {

            get { return GetValue(ModelProperty); }

            set { SetValue(ModelProperty, value); }

        }

 

        public static readonly DependencyProperty ModelProperty =

            DependencyProperty.Register("Model", typeof(object), typeof(MVVMAnimationBehavior), new PropertyMetadata(HandlModelChanged));

 

        private static void HandlModelChanged(object sender, DependencyPropertyChangedEventArgs e)

        {

            MVVMAnimationBehavior behavior = sender as MVVMAnimationBehavior;

            object model = behavior.Model;

            if (behavior.info != null)

            {

                behavior.info.RemoveEventHandler(model, Delegate.CreateDelegate(typeof(EventHandler), behavior, "RunAnimation"));

            }

            if (model != null && !string.IsNullOrEmpty(behavior.EventName))

            {

                behavior.info = model.GetType().GetEvent(behavior.EventName);

                behavior.info.AddEventHandler(model, Delegate.CreateDelegate(typeof(EventHandler), behavior, "RunAnimation"));

 

            }

        }

 

        private void RunAnimation(object sender, EventArgs e)

        {

            if (AnimationStoryBoard != null)

            {

                AnimationStoryBoard.Begin();

            }

        }

    }

}

 

 

As you can see, I added two mode dependency properties – one for event name that will trigger the animation, the other one for ViewModel ( I actually called it model).  Now the tricky part is to use a bit of reflection to attach an event handler to the event on my model.  This is done in HandlModelChanged routine that is called when Model or Event name is set.  I am getting an event, and attaching a handler to it.  The actual handler is located inside the behavior itself – RunAnimation method.  Here is what my fianl XAML looks like that is testing both animation approaches:

<UserControl x:Class="SLMVVMAnimationBehavior.MainPage"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    xmlns:local="clr-namespace:SLMVVMAnimationBehavior"

    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">

    <UserControl.Resources>

        <Storyboard x:Name="TestStoryboard">

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="textBlock" Storyboard.TargetProperty="(TextBlock.FontSize)">

                <EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="24"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.2000000" Value="21.333"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.3000000" Value="18.667"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.4000000" Value="16"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.5000000" Value="13.333"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.6000000" Value="16"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.7000000" Value="18.667"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.8000000" Value="21.333"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.9000000" Value="24"/>

                <EasingDoubleKeyFrame KeyTime="00:00:01" Value="26.667"/>

            </DoubleAnimationUsingKeyFrames>

        </Storyboard>

        <local:SampleModel x:Key="CurrentModel" />

        <local:MVVMAnimationBehavior AnimationStoryBoard="{StaticResource TestStoryboard}" Model="{StaticResource CurrentModel}" x:Key="Animation" EventName="StartAnimation"/>

    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" Background="#FFF3EEEE" DataContext="{Binding Source={StaticResource CurrentModel}}">

        <Grid>

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="Auto"/>

                <ColumnDefinition Width="Auto"/>

                <ColumnDefinition/>

            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>

                <RowDefinition Height="Auto"/>

                <RowDefinition/>

            </Grid.RowDefinitions>

            <Button x:Name="TestButton" Content="Click To Start Animation" d:LayoutOverrides="Height" HorizontalAlignment="Left" Click="TestButton_Click"/>

            <Button Content="Behavior Test" Grid.Column="1">

                <i:Interaction.Triggers>

                    <i:EventTrigger EventName="Click">

                        <local:MVVMAnimationBehavior AnimationStoryBoard="{StaticResource TestStoryboard}"/>

                    </i:EventTrigger>

                </i:Interaction.Triggers>

            </Button>

            <TextBlock x:Name="textBlock" Margin="0,0,0,6" Text="Sample Text" TextWrapping="Wrap" d:LayoutOverrides="Width, Height" Grid.Row="1" Grid.ColumnSpan="3" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="26.667"/>

        </Grid>

 

    </Grid>

</UserControl>

 

To summarize, I illustrate a couple of approaches to trigger animations in MVVM environment.  Of course, there is always code-behind, but many developers frown at this approach..

Please let me know if you have any questions.

WCF RIA Services Validation

Today I am continuing exploring WCF RIA Services.  I am going to discuss validation in RIA Services.

Any business application needs to validate user input.  I am going to start with a simple case.  In my sample application a user can enter a company information.  I would like to setup RIA Services to force the user to enter a company name before he or she can save the company.  In order to do so I am going to use Data Annotations.  First of all, I need to add a reference to System.ComponentModel.DataAnnotations DLL to all my projects.  RIA Services project should already have the reference. 

Now I need to edit my metadata file that corresponds to my data model under .NET version of RIA Services.  In my case it is RolodexDomainService.metadata.cs file in SilverlightRIAServicesLibrary.Web project.  In that file I need to find Companies class, then location company name property, then decorate the property with required attribute.  At the same time we will also put a limit on how many characters a user can enter:

[Required]

[StringLength(30)]

public string CompanyName;

 

If we want to see the results of our changes, we can run the application, then clear company name for an existing comp-any, then tab out of company name field.  Here we get visual feedback that our input was not valid:

image

Now, let’s create custom validation.  Fir example, I am going to force the date added to be no less that 1/1/2000.  To do this I will write a custom validation class like so:

public static class ValidationHelper

{

    public static ValidationResult DateAddedCheck(DateTime date)

    {

        ValidationResult result;

        if (date > new DateTime(2000, 1, 1))

        {

            result = new ValidationResult("");

        }

        else

        {

            result = new ValidationResult("Date is not valid");

        }

 

        return result;

    }

}

Validation method that I wrote is a static member.  It follows a specific signature that RIA Services requires.  For example, it returns Validation Result that contains specific information that validation infrastructure of RIA Services can parse.  Overall code is fairly simple.

In order to make this class available on the Silverlight side, I must include my validation class into Silverlight version of RIA Services library – SilverlightRIAServicesLibrary project in my case.  In order not to duplicate the code, I will include the same class as a link.  I right-click on the project, choose add existing item, navigate to my class, then click on down arrow on Add button, and select Add As Link.  Now I have the same validation on both .NET and Silverlight side.  To confirm, I just build and run the application.  Here is what my DateAdded attributes look like:

[Required]

[CustomValidation(typeof(ValidationHelper), "DateAddedCheck", ErrorMessage = "Date is not valid")]

public DateTime DateAdded;

On important thing to mention that in  order to see validation error in UI, we need to update our Binding to look as following:

<TextBox x:Name="CompanyNameTextbox" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Stretch" Margin="6,6,6,6" Text="{Binding Path=CompanyName, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" VerticalAlignment="Center"/>

There is one important thing to notice.  If you look at Silverlight side generated code, you will notice that validation occurs before the property value is set.  As a result, you cannot rely on property value being set if a validation exception is thrown.

Now, let’s look at saving code that we had to modify in order to validate user input.  Here is what it looks like:

try

{

    Validator.ValidateObject(this.Model, new ValidationContext(this.Model, null, null), true);

    if (this.Model.HasChanges)

    {

        ShowPleaseWaitMessage();

        _context.SubmitChanges(HandleSave, null);

    }

}

catch (ValidationException ex)

{

    MessageBox.Show(ex.Message);

}

Not really the cleanest code because we have to rely on exceptions being thrown. 

I covered all key area of validation, but there is more for you to explore.  Please let me know if you have any questions.

Windows Azure

I just want to relay Microsoft’s new offer to everyone.  Windows Azure is now offered for free for a limited time.  This is an introductory offer to get more people to use new cloud platform from Microsoft.  Please see this link for details.

Speaking at Atlanta .NET Users Group

I spoke at Atlanta.NET Users Group yesterday, My topic was Azure Step-by-Step.

I talked about why someone would use Windows and SQL Azure, then I built a Silverlight application from scratch.  The application was designed to run in Windows Azure and use SQL Azure as database.  I demonstrated how to get maximum code re-use between traditional .NET web application and the same application developed for Azure.  At the end, I had an application that could run on either platform with just web.config change.

You can download the zip file with PowerPoint slides with useful links as well as the sample project I built here.

Please let me know if you have any questions.