CRM Development

Solutionist has designed the architecture for a new CRM system for use in the medical imaging industry.

Thursday 23 February 2012

Primary Keys in Entity Framework and Sync Framework - Part 2

In Part 1 we considered various options when it came to using Microsoft Sync Framework with Entity Framework.

After a certain amount of pain we seem to have got to something approaching a settled condition.
  1. We didn't want IDs that were GUIDs as this would make them unreadable. So, we are keeping Primary keys as simple ID columns.
  2. Because of this, we went for a solution that would reseed the local tables on each client to a known range. After each synchronisation, the tables would be reseeded to the correct value. That way entries created on the client/server would have different IDs and wouldn't clash
  3. We had to use SQL Server Express on the clients.
Number (3) above is a long story...

  • SQL Compact 4 won't play nicely with Entity Framework or the Sync Framework (Link here and here )
  • SQL Compact 3.5 wouldn't play nicely with the various items - follow this link and see the section "Limitations of SQL Server compact" - basically it can't:
    • "support entities with server-generated keys or values when it is used with the Entity Framework ".
There's a lot of other things that SQL server compact can't do - including supporting stored procedures. So that's how we ended up back at SQL Server Express.

I hope this gives you a flavour of the sort of things to consider when looking at data replication on SQL Server.

You're going to ask why didn't we use SQL Server Merge Replication - that's another story and another post...

Wednesday 22 February 2012

Architecture Note

A short note on architectures for WCF-based solutions - we've found this works for us.


All classes that are being passed across the wire must be serialisable and each property must be annotated.

The WCF service is nothing more than a thin facade on top of a call to Business Logic. 
In fact it's a one-to-one relationship to the Business Logic calls... The Service layer just exposes the business logic so that it can be used in creating bindings, etc.


Business Logic - as they say, it "does the business" and calls the data access.layer.
Data Access Layer - we're using Repository pattern with Entity Framework.

Throughout, we've using IoC (Ninject) to hook data access repositories into the Business Layer and Business Logic into the Service Layer. This has meant inserting Ninject into the WCF factory pipeline - see this post.

OK, you may ask why create a WCF facade on top of the business logic?

Well, doing this lets you create clean classes and "unit" tests for the business logic without  bothered about annotations, etc for WCF.
It also means that the Business Logic layer becomes a re-usable component - where you don't have to include WCF-related annotations and dlls.

Thursday 2 February 2012

How to get a WPF TextBox to update its ViewModel binding variable

A short post:

Scenario:
You're using MVVM and have bound a textbox to a string ViewModel property - in TwoWay mode.

You have a button that is only to be enabled when that string property is not null/empty. 

Problem: 
You type in the textbox, but the button remains firmly disabled until the textbox loses focus.
Only at that point is the string's PropertyChanged event raised.

Solution:
(Taken from  http://betaforums.silverlight.net/forums/t/103695.aspx )
Do the following on the TextBox's TextChanged event:
      void summaryTextBox_TextChanged(object sender, TextChangedEventArgs e)
      {
          TextBox txCtl = (TextBox)sender;
          if (txCtl != null)
          {
              var be = txCtl.GetBindingExpression(TextBox.TextProperty);
              if (be != null)
              {
                  be.UpdateSource();
              }
          }
       }
This will force the PropertyChanged event to be raised whenever the text is changed - and your button will be enabled as soon as you start typing in the TextBox.

Wednesday 1 February 2012

More .NET IoC - Using Ninject in WCF Services

I've seen other postings about this, but thought I'd add my own 2p-worth since I had to struggle a bit to get it working.

The basic idea is to use Ninject in the WCF pipeline and get WCF use Ninject to create the service. Then you can take advantage of Ninject's IoC to manage dependencies.

I used the base Ninject and the Ninject Web and Wcf extensions - all available via NuGet.

To integrate ninject into the WCF service pipeline, create a "normal" WCF service but add the following to the .svc file

Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory" 


So, the file would look something like:


<%@ ServiceHost Language="C#" Debug="true" Service="WcfService.GeneralService" 
CodeBehind="GeneralService.svc.cs" 
Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory" %>


Then you can inject dependencies into the service as needed as follows:


[Inject]
public IUsersRepository _repository { private get; set; }

Now we're assuming that you're using a WCF application project - so, to initialise Ninject correctly you need to make changes to the WCF project Global.asax file as follows:


  1. Make Global extend NinjectWcfApplication   (from Ninject.Extensions.Wcf)
  2. Implement and override CreateKernel - so the file looks like this:

    public class Global : NinjectWcfApplication

    {
    // Other methods omitted for clarity...
 
        protected override Ninject.IKernel CreateKernel()
        {
            IKernel k =  new StandardKernel(new ServiceModule());
            return k;
        }
    }


Now the ServiceModule is a Ninject module that would look something like:


    public class ServiceModule : NinjectModule
    {
        public override void Load()
        {
            Bind().To();
        }
    }


Notice that we're binding the IUsersRepository to the UsersRepository implementation.

Doing this will enable Ninject to do its magic in the WCF service above where it is injected.

When Service is invoked, the Ninject factory will instantiate the class and so be able to use the module bindings to pull in the correct interface implementations.

Notice that you don't need to change service bindings, etc.