Tuesday, January 15, 2013

Asynchrounous programming aka async and await support in Windows, Windows RT and Windows Phone

The new async/await syntax of C# 5 is natively supported in WinRT, .NET 4.5 and Windows Phone 8. Up until 22 Oct 2012 it was additionally available for .NET 4.0 and Silverlight 5 via the Async Targeting Pack from June 2012.

On 22 Oct 2012, Microsoft pre-released a package called Microsoft.Bcl.Async additionally for Silverlight 4, Windows Phone 7.5 and, what's probably most surprising, also for Portable Class Libraries targeting all these platforms:

Using async/await without .NET Framework 4.5:

To add a reference to the updated NuGet Package, right click the project, select “Manage Package References” and search for Microsoft.Bcl.Async. Make sure you selected the “Online” tab on the left hand side and the top left drop down says “Include Prerelease”.

Tuesday, January 08, 2013

WCF Data Services + oData + Entity Framework + Silverlight + Telerik simple application

At the time writing this article, WCF Data Services(previously known as ADO.NET Data Services) ships separately from .NET Framework and are distributed by NuGet.

This means, the namespace used is in the form Microsoft.Data.Service.* and not System.Data.Service* (like in .NET Framework). The new release supports oData v3, while the previous release of WCF Data Services existing in .NET Framework supports oData v1 and v2.

This is described here: http://msdn.microsoft.com/en-us/data/ee720179

The Telerik suite has a nice support for WCF Data Services by the RadDataServiceDataSource class, which is able to bind the data from WCF Data Service to the UI.

http://www.telerik.com/help/silverlight/raddataservicedatasource-overview.html

One problem is Telerik was built against the .NET Framework support for WCF Data Services, not against the assemblies distributed by NuGet.

Read more about this here: http://www.telerik.com/community/forums/silverlight/dataservice-datasource/raddataservicedatasource-problem-visual-2012.aspx

 

Steps to create the app:

1. Create a new Silverlight 5 application using Web Application project setting, and suppose the name of the app is SilverlightApplication1

The next steps refer to the web application:

2. I wanted to have a code behind class for the generated SilverlightApplication1TestPage.aspx, so I added a SilverlightApplication1TestPage.aspx.cs class, and in the SilverlightApplication1TestPage.aspx I added:

CodeBehind="SilverlightApplication1TestPage.aspx.cs" Inherits="SilverlightApplication1.Web.SilverlightApplication1TestPage"

Also, I made SilverlightApplication1TestPage to derive from System.Web.UI.Page

3. Add references to System.Data.Services, and System.Data.Services.Client to add support for WCF Data Services.

Also, rigth click on the web project and choose “Manage NuGet packages”. In the top right search box, search for Entity Framework and when found, click on Install button. It will add a reference to EntityFramework assembly.

4. Create a class for an entity called User:

[DataServiceKey("Id")]
[DataServiceEntity]
public class User
{
    [Key]
    public virtual int Id { get; protected set; }
    public virtual string FirstName { get; protected set; }
    public virtual string LastName { get; protected set; }
}

The DataServiceKey and DataServiceEntity attribute need to be set to tell WCF Data Services which is the Id property of the class entity.

5. Create a class derived from DbContext, UserContext

public class UserContext : DbContext
    {
        public DbSet<User> Users
        {
            get;
            set;
        }

        public UserContext(string connString) : base(connString)
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new UserMapping());
            base.OnModelCreating(modelBuilder);
        }
    }

We can expose the User entity by the WCF Data Service using a public property returning a DbSet of that entity

The DbContext constructor accepts a string which represents the connection string to the database

6. Add a UserMapping class which implements the mapping of the User entity to database, so for Entity Framework to know how to do it

public class UserMapping : EntityTypeConfiguration<User>

{
        public UserMapping()
        {
            this.HasKey(t => t.Id);
            this.Property(t => t.FirstName).IsRequired().HasMaxLength(50);
            this.Property(t => t.LastName).IsRequired().HasMaxLength(50);
        }
    }

7. Right click on the web app project, and choose Add New Item/click on Web/WCF Data Service and choose UserService.svc as the name.

[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    public class UserService : DataService<ObjectContext>
    {
        public static void InitializeService(DataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("*", EntitySetRights.All);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
            config.UseVerboseErrors = true;
        }

        protected override ObjectContext CreateDataSource()
        {
            var connString = ConfigurationManager.ConnectionStrings["DBConnString"].ConnectionString;
            var context = ((IObjectContextAdapter)new UserContext(connString)).ObjectContext;
            context.ContextOptions.ProxyCreationEnabled = false;
            return context;
        }
    }

The ServiceBehavior attribute makes the web-service to include the exception in the fault details. It is important when debugging.

Fiddler is good to debug web-service issues and this attribute will make the exceptions visible in the response.

SetEntitySetAccessRule is important to set rights on entities.

TestQueryableSL is the name of the connection string to the database

8.  Add the following to the web.config:

<connectionStrings>
    <add name="DBConnString"
         connectionString="Server=YourPCName;Database=Test;Trusted_Connection=True"
         providerName="System.Data.SqlClient"/>
      </connectionStrings>

<system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>

You should have a database called Test. If not, open SQL Server Management, and add a new database called Test.

In the Silverlight app:

9. Add a new class UserDataCtx:

public class UserDataCtx : UserContext
{
    public UserDataCtx()
        : base(new Uri("
http://localhost:4232/UserService.svc", UriKind.RelativeOrAbsolute))
    {
    }
}
Instead of 4232 port, use the port from right click on Web app project/ Web tab/Use Visual Studio Development Server/Specific port

This class is required in order to pass the Uri to the UserContext class

 

10. In MainPage.xaml add:

xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:l="clr-namespace:SilverlightApplication1"

<Grid x:Name="LayoutRoot"
         Background="White">
       <Grid.RowDefinitions>
           <RowDefinition Height="*" />
           <RowDefinition Height="Auto" />
       </Grid.RowDefinitions>
       <telerik:RadDataServiceDataSource Name="customersDataSource"
                                         QueryName="Users"
                                         AutoLoad="True">
           <telerik:RadDataServiceDataSource.DataServiceContext>
               <l:UserDataCtx />
           </telerik:RadDataServiceDataSource.DataServiceContext>
       </telerik:RadDataServiceDataSource>
       <telerik:RadGridView Grid.Row="0"
                            ItemsSource="{Binding DataView, ElementName=customersDataSource}"
                            IsBusy="{Binding IsBusy, ElementName=customersDataSource}"
                            ShowGroupPanel="False" />
       <telerik:RadDataPager Grid.Row="1"
                             Source="{Binding DataView, ElementName=customersDataSource}"
                             PageSize="10" />
   </Grid>

11. Right click on the Silverlight project and add a new service reference. Click on the arrow button from Discover button, and choose ‘Services in this solution’

You should see UserService.svc in the list and selected.

In the Namespace text box, choose the name DataServices

12. Add reference to the Telerik.Windows.Controls/Data/DataServices/GridView/Input  and Telerik.Windows.Data

Wednesday, December 19, 2012

NHibernate Inverse and Cascade

Best explanation: http://www.emadashi.com/2008/08/nhibernate-inverse-attribute/

Suppose we have a Parent with a collection of Child objects (one to many)

public class Parent

{

public virtual int Id { get; set; }

public virtual string Name { get; set; }

public virtual IList<Child> MyChildren { get; set; }

}

public class Child

{

public virtual int Id { get; set; }

public virtual string Name { get; set; }

public virtual Parent MyParent { get; set; }

}

 

Parent par = Session.Get<Parent>(8);

Child ch = new Child();

ch.Name = “Emad”;

par.MyChildren.Add(ch);

Session.Save(par);

 

First, we need to set the cascade on the MyChildren, such that when ever you save the Parent, all the Child objects in the MyChildren collection are forced to be saved as well.

Also, by default, the parent object will also set the ParentId column on the newly inserted Child, because there is a hidden property on the MyChildren collection which is by default false. This means the Parent object will manage the relationship by updating the ParentId foreign key on the child row.

So what will happen is:

1. the new child is added

2. the new child ParentId foreign key is updated

The problem comes when you put the null constraint on the MyParent, the insert will fail because the ParentId is not yet set.

To overcome the issue, the solution is to:

1. set inverse attribute to false for the MyChildren collection. this will not update the ParentId foreign key anymore on the Child

2. explicitly set the Parent property in code for the Child object

Parent par = Session.Get<Parent>(8);

Child ch = new Child();

ch.Name = “Emad”;

ch.MyParent = par;

par.MyChildren.Add(ch);

Session.Save(par);

SaveOrUpdate Vs Update and Save in NHibernate

Chapter 9 :

http://www.nhforge.org/doc/nh/en/index.html

But cliff notes:

Save() takes a new object without an identifier and attaches it to the session. The object will beINSERT'd.

Update() takes an existing object that has an identifier but is not in the session and attaches it to the session. The object will be UPDATE'd.

SaveOrUpdate() looks at the identifier and decides what is necessary in the above.

SaveOrUpdateCopy() is special in that say you have two objects with the same identifier -- one in the session and one not. If you try and update the one not in the session an exception is thrown normally (you are now trying to attach two objects that represent the same persistent object to the session).SaveOrUpdateCopy() copies the non-session object state to the session object state.

I'm not sure how you are going to use NH, but for a lot of cases all you need is Save(). The session is doing ALL of the work necessary to know what has to be updated and simply Flush() or a Commit()does everything you need.

You usually don't need SaveOrUpdate() because NHibernate tracks changes to every loaded object. To update an object use Session.Get(), make you change then call Session.Flush()

NHibernate defaults

Nullable – yes, all properties are nullable by default
Lazy – yes, all properties are lazy by default. They must be virtual and public or protected.
Cascade – default is None
Inverse - default is false, meaning this side is maintaining the relationship

NHibernate Get vs Load behavior in whether returning the proxy or not

When returning an entity by using Get or Load, NHibernate first tries to return it from the session cache.
If it’s not there, then Get and Load will return the entity in a different way.
When calling Get, NHibernate will perform a roundtrip to database and return the non-proxy entity object or null in case the record does not exist:
var user = session.Get<User>(122);
For Load, NHibernate will return a proxy of the entity object or throw an exception if the record does not exist:
var user = session.Load<User>(122);
Suppose we have the following calls:
var a = session.Load<Assignment>(1);
var b = session.Get<Assignment>(1);
Note that in the 2nd case, b is a proxy and not the entity because the entity proxy exists in the session cache due to the Load call.
var a = session.Get<Assignment>(1);
var b = session.Load<Assignment>(1);
In this case b is a non-proxy entity object, due to the Get call.

Friday, November 16, 2012

Remote debugging in Visual Studio, target on a different domain

My computer is a Windows 7 32bits and I had to debug a ASP.NET 32 bit worker process running on a Windows Server 2008 64 bit machine.

The server is in a VPN and in a domain.

What I did was, on the server, I first ran this tool:

Start\Programs\Microsoft Visual Studio 2010\Visual Studio 2010 Remote Debugger (x86)

Make sure your user has permissions to debug the apps, so you can go to Tools\Options and click on Permissions. Your user should have Debug permission.

The tool says “Msvmon started  a new server  named ‘JohnDoe@VMXXXXXX. Waiting for connections’.

Now, in Visual Studio 2010 on my machine, I went to “Debug\Attach to Process” and in Qualifier, I put JohnDoe@XX.XX.XX.XX where XX.XX.XX.XX is the IP of the server. Note that I didn’t use the ‘JohnDoe@VMXXXXXX’. It didn’t work for me.

Two things worth mentioning:

1. you need to have the same user and password on the local machine. I created a separate account on my machine for this.

2. you cannot debug 64 bit processes from a 32 bit machine. Luckily, my processes were running as 32 bit processes so I could debug them.