How to use WAQS?

7 reasons to use WAQS

WAQS documentation

 

WAQS could be used in many kinds of applications. Some of my customers already use it for these kinds ones:

  • 3-Tiers application
  • Web application (ASP.NET MVC)
  • Web service

In this post, I will describe 3-Tiers application scenario.

3-Tiers application:

3-Tiers application is the default scenario. WAQS was initially made for it.

Architecture

Layers and dependences

A first choice of WAQS, is to choose a layered architecture, a sane split, often use in real world, in which each layer has its own responsibility. Abstractions between layers reduce coupling for a better flexibility and a better testability.

With this approach, WAQS also reduces dependences with used technologies like Entity Framework or WCF for example.

WAQS architecture

The default architecture of an application using WAQS will be the following (with all dark blue layers generated by WAQS):

image

How to generate the code with WAQS?

As we can see in the previous schema, to use current version of WAQS, you will need to use an edmx. In most cases, it’s the first thing you have to create.

Note that in the current version of WAQS, you must use two ways associations (with the two navigation properties) and include FKs.

 

In addition, note that there is a bug on T4 in VS 2013. It works with VS 2012 but with VS 2013 you have to run all T4 templates in Debug mode to be able to use WAQS.

 

In order to be able to generate the code, you first have to install WAQS visual studio extension for the first WAQS usage (as Administrator).

 

With VS 2012, you can do it in Tools/Extensions and Updates. Then if you search WCFAsyncQueryableServices, you will find the WAQS extension. Install it.

Note that to install it, you have to close all other Visual Studio instances.

After installing it, you have to restart VS.

 

With VS 2013, close all instances of VS and download and install Roslyn End Preview vsix and WAQS vsix.

 

Then, in order to be able to generate the server part, you have to install WCFAsyncQueryableServices.Server NuGet package.

To install this package, you can write the following command in the Package Manager Console:

Install-Package WCFAsyncQueryableServices.Server

Note that for your first usage of each WAQS NuGet package version, you have to do it with administrator rights.

Installation of this package won’t change your project but will add a new PowerShell command on the Package Manager Console.

Then, you can use it to generate WAQS code using WCFAsyncQueryableServicesServer command.

For example:

WCFAsyncQueryableServicesServer ‘"C:\VS Projects\WAQSDemo\WAQSDemo.Web\Northwind.edmx"’ All Web

Note that you have the intellisense for it. So you can just write WCFA<tab> <tab> <tab> <tab>.

Note that Web is the default value so it’s useless here. You can choose App instead if you want to use a two tiers application (Web for Web.config, App for App.config). 

Furthermore you have several other options than All. We will talk about it in a future post.

 

Now we have the server code and we will see the client tier.

 

For the client tier, we have a special WPF version and a PCL one (with few restrictions) which is usable in many projects like W8, WP8, but also with iOS and Android via Xamarin (some of my customers did it). Note that today WCF is not completely supported by Xamarin and so you have many restrictions in WAQS with it but, anyway, WAQS could be used in this applications too.

WPF

For the client side, it’s the same way than for the server one.

So, first, install the NuGet package:

Install-Package WCFAsyncQueryableServices.Client.WPF

Then, select the good project in the Package Manager Console

image

Then, you can execute the client generator new PowerShell command still with intellisense:

WCFAsyncQueryableServicesClientWPF ‘"C:\VS Projects\WAQSDemo\WAQSDemo.Web\Northwind.edmx"’ ‘"C:\VS Projects\WAQSDemo\WAQSDemo.Web\Northwind.svc"’ All

When the generation ends you can create a ViewModel class.

After creating it, you should have a default class like this one:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WAQSDemo.Client.WPF
{
    class MainWindowViewModel
    {
    }
}

The Nuget package also added two other commands: WCFAsyncQueryableServicesGlobalClientWPF we will see in a future post and WCFAsyncQueryableServicesApplyViewModelWPF.

We will use this one (still with intellisense):

WCFAsyncQueryableServicesApplyViewModelWPF "Northwind" ‘"C:\VS Projects\WAQSDemo\WAQSDemo.Client.WPF\MainWindow.xaml"’

After executing it, the ViewModel is now like this one:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfApplication1;
using WpfApplication1.ClientContext;
using WpfApplication1.ClientContext.Interfaces;
using WpfApplication1.ClientContext.Interfaces.Errors;
using WCFAsyncQueryableServices.ClientContext;
using WCFAsyncQueryableServices.ClientContext.Interfaces;
using WCFAsyncQueryableServices.ClientContext.Interfaces.Errors;
using WCFAsyncQueryableServices.ClientContext.Interfaces.Querying;
using WCFAsyncQueryableServices.ComponentModel;
 
namespace WAQSDemo.Client.WPF
{
     public class MainWindowViewModel : ViewModelBase
     {
         private INorthwindClientContext _context;
         public MainWindowViewModel(INorthwindClientContext context): base (context)
         {
             _context = context;
         }
     } }


And the constructor of the MainWindow.xaml.cs is now this one:



public MainWindow(WAQSDemo.Client.WPF.MainWindowViewModel vm)
{
     InitializeComponent();
     DataContext = vm; }


So now, in your ViewModel, you have a field of type INorthwindClientContext that can be used to querying your data or saving changes and many other things we will see in the future.



 



Note that every queries supported by LINQ To Entities is usable in LINQ To WAQS (in fact you can do more with LINQ To WAQS).



LINQ To WAQS is asynchronous. To execute a LINQ To WAQS query, you have to use two methods: AsAsyncQueryable and Execute.



var customers = await (from c in _context.Customers.AsAsyncQueryable()
                       select c).ExecuteAsync();




PCL



With current version of WAQS PCL, you must include SL5 and .NET 4.5 (others are optional like WP8 and W8 but note that WP7 or WP7.5 are not supported).



Then, it’s the same process:



Install-Package WCFAsyncQueryableServices.Client.PCL



WCFAsyncQueryableServicesClientPCL ‘"C:\VS Projects\WAQSDemo\WAQSDemo.Web\Northwind.edmx"’ ‘"C:\VS Projects\WAQSDemo\WAQSDemo.Web\Northwind.svc"’ All



The only one difference is on ApplyViewModel because there is no associated view with PCL:



WCFAsyncQueryableServicesApplyViewModelPCL "Northwind"



Then, you have to write the WCF configuration yourself (note that WCF configuration is generated by WAQS with WPF client). If you have an App.config on your client, you can use it to define WCF configuration or you can only use code. For example, in a W8 app, we can use it with this way:



Add a method to SetContext in the MainPage:



public void SetDataContext(PCLViewModel viewModel)
{
     DataContext = viewModel; }


And in the App.xaml.cs, you can use the following code:



protected override void OnLaunched(LaunchActivatedEventArgs args)
{
     Frame rootFrame = Window.Current.Content as Frame;
     if (rootFrame == null)
     {
         rootFrame = new Frame();
         Window.Current.Content = rootFrame;
     }
     if (rootFrame.Content == null)
     {
         if (!rootFrame.Navigate(typeof(MainPage), args.Arguments))
         {
             throw new Exception("Failed to create initial page");
         }
         ((MainPage)rootFrame.Content).SetDataContext(GetMainPageDataContext());     }
    Window.Current.Activate(); } private PCLViewModel GetMainPageDataContext() {
     IUnityContainer expressionUnityContainer = new UnityContainer();
     expressionUnityContainer.RegisterType<IExpressionTransformer, ExpressionTransformer>();
     ExpressionTransformerFactory.Factory = () => expressionUnityContainer.Resolve<IExpressionTransformer>();
     IUnityContainer unityContainer = new UnityContainer();
     InitWCFAsyncQueryableServicesModules(unityContainer);
     return unityContainer.Resolve<PCLViewModel>(); } private void InitWCFAsyncQueryableServicesModules(IUnityContainer unityContainer) {
     var binding = new CustomBinding();
     var binaryMessageEncodingBindingElement = new BinaryMessageEncodingBindingElement { MaxSessionSize = int.MaxValue };
     binaryMessageEncodingBindingElement.ReaderQuotas.MaxArrayLength = int.MaxValue;
     binaryMessageEncodingBindingElement.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
     binaryMessageEncodingBindingElement.ReaderQuotas.MaxDepth = int.MaxValue;
     binaryMessageEncodingBindingElement.ReaderQuotas.MaxNameTableCharCount = int.MaxValue;
     binaryMessageEncodingBindingElement.ReaderQuotas.MaxStringContentLength = int.MaxValue;
     binding.Elements.Add(binaryMessageEncodingBindingElement);
     var httpBindingElement = new HttpTransportBindingElement { MaxBufferSize = int.MaxValue,
        MaxReceivedMessageSize = int.MaxValue };
     binding.Elements.Add(httpBindingElement);
     var endPointAddress = new EndpointAddress(http://localhost:13117/Northwind.svc);
     unityContainer.RegisterType<INorthwindService, NorthwindServiceClient>(new InjectionConstructor(binding,
        endPointAddress));
     unityContainer.RegisterType<INorthwindClientContext, NorthwindClientContext>(); }


 



If you have any comment / issue, you can use the CodePlex web site: https://waqs.codeplex.com/

This entry was posted in 16868, 17894, 17895, 18204, 8708. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>