Showing posts with label RIA Services. Show all posts
Showing posts with label RIA Services. Show all posts

Wednesday, May 8, 2013

CLASS Services

The next version of CLASS extensions is going to be available by the end of summer with some really interesting goodies added. But, with HTML client (even before it’s official release) being in the center of interest, I feel like Silverlight extensions, are going to be soon, if not already, out of demand.
So, until I find the time to catch up with HTML client, I though on focusing more to stuff that are client implementation independent. That’s why, apart from the next version of CLASS Extensions for Silverlight clients, I plan on releasing a Server/Common side extension pack called CLASS Services.
If you are one of the blessed people Angel that purchased CLASS Extensions, you already know of File Server service included, that provides file based content access to your server.
Two more of the services that are going to be included in this new CLASS Services pack can be found in this sample I posted in MSDN. Ok, I am not crazy, I know that if I share the code no-one will buy the extensions, but these two simple (as regards to the coding effort) services, are just a part of what CLASS Services is going to include. Either way, I believe my Lightswitch community contribution, even if not as extensive and steady as other people’s, makes clear that the idea is sharing and not making money out of it.
Regarding the sample, I must underline that the application itself is just an example. And I want to stress this point, because some would say that, what the sample application displays is not DI. The idea of the sample was not to display DI in action but just to display how you bind the RIA services together, to do whatever you like. MEF is used as a DI framework by the RIA Service to provide the required functionality.
Also, I have to admit that if properly implemented, by the book, restrictions and conventions in imports and exports of MEF (or any other DI framework for that matter) would make any additional configuration (like the one my sample suggests) pointless.
Nevertheless, IMHO, you really have to be a DI purist, not to recognize the potential provided by these two services. An example: In Computer Life, we plan (George stop calling me names Smile with tongue out) to implement a generic (extension) way to support EAV model in our Lightswitch applications. It’s so obvious how useful the Domain Types RIA service will be for this implementation that I won’t even bother writing anything to prove it.
Anyway, I hope you find these two RIA services useful. I realize you have to go far beyond the “Coding is optional” motto to make good use of this kind of services, but I believe the Lightswitch development community, has already given the answer to that (not at all well-intentioned) “It’s the next MS-Access” hype…

Friday, June 22, 2012

RIAlity Issues

Recently I had to face a very frustrating issue regarding the integration of a RIA Service as a LightSwitch Datasource. I tried to find references for it in the web. I did. But none of them (at least the ones I managed to find) didn’t seem to match my case. So after solving my issue I thought sharing was a good idea…
After having implemented and tested my RIA service using a small Silverlight application I decided to add a datasource and use it. Which I did. Focusing at the part of the RIA service that caused the problem, I had a class called ImageAttachment and 2 queries exposing it. Below you can see the initial code:
   1:      [Query(IsDefault = true)]
   2:      public IQueryable<ImageAttachment> GetImageAttachments() {
   3:        return new List<ImageAttachment>().AsQueryable();
   4:      }
   5:   
   6:      public IQueryable<ImageAttachment> GetFolderItemImageAttachments(Guid? providerId, string folderId, string mailItemId) {
   7:        if (!providerId.HasValue || folderId == null || mailItemId == null)
   8:          return GetImageAttachments();
   9:        return GetAttachments(providerId.Value, folderId, mailItemId);
  10:      }



Importing the RIA Service GetFolderItemImageAttachments was properly imported as an optional query for ImageAttachment.

image

I added an ImageAttachment visual collection in a screen fetching results from GetFolderItemImageAttachments query. Everything worked smoothly. But when the time came to load the visual collection (i.e. run the query) I got an exception I hadn’t come across before neither as a LS developer nor as a Silverlight one:

Load operation failed for query ‘GetFolderItemImageAttachments’.  The remote server returned an error: NotFound.

The behavior was very strange. Although the query was recognized and imported from LS for some reason at runtime it looked like the method was not found. I placed a breakpoint at the method and it didn’t hit. The method was never called. Before doing this I was sure it was some bug of mine in the implementation that caused the RIA service to throw this generic exception. But no! The execution never reached the web method. It was then that I decided to “google” it. Looked like it was a RIA Services+LightSwitch(?) issue. All references where either not appropriate in my case or had no effect. Then I did what I usually do when I have problem I cannot solve: I scrolled to the part of code listed above and started to just stare at the code waiting for an answer. And I came to me! Why not make sure the query method IS a query? So what I did was just add the QueryAttribute to my method with no parameters:

   1:      [Query(IsDefault = true)]
   2:      public IQueryable<ImageAttachment> GetImageAttachments() {
   3:        return new List<ImageAttachment>().AsQueryable();
   4:      }
   5:   
   6:      [Query]
   7:      public IQueryable<ImageAttachment> GetFolderItemImageAttachments(Guid? providerId, string folderId, string mailItemId) {
   8:        if (!providerId.HasValue || folderId == null || mailItemId == null)
   9:          return GetImageAttachments();
  10:        return GetAttachments(providerId.Value, folderId, mailItemId);
  11:      }




I thought that if it didn’t solve the problem I surely would not cause a new one. It IS a query method after all. Why let LS infer it? And it worked.

I am quite sure I was lucky. I mean, the query was recognized either way. I cannot explain what exactly was the bug the QueryAttribute fixed. To stress my point more, I have to admit that went back to the RIA Service and I removed the attribute. Still worked! Like a deadlock resolved. Maybe only LightSwitch Team can explain. Anyhow I thought of sharing in case anyone else runs into something like this.Smile

Sunday, November 20, 2011

Auditing and Concurrency don’t mix (easily)…

In MSDN forums I came across a post addressing an issue I have also faced. Auditing fields can cause concurrency issues in LightSwitch (not exclusively).
In general basic auditing includes keeping track of when an entity was created/modified and by whom. I say basic auditing because auditing is in general much more than this.
Anyhow, this basic auditing mechanism is very widely implemented (it’s a way for developers to be able to easily find a user to blame for their own bugs :-p), so let’s see what this can cause and why in LightSwitch.
In the aforementioned post but also in this one, I have clearly stated that IMHO the best way to handle concurrency issues is using RIA Services. If you don’t, read what follows.
Normally in any application, updating the fields that implement Audit tracking would be a task completed in the business layer (or even Data layer in some cases and this could go as deep as a database trigger). So in LightSwitch the first place one would look into to put this logic would be EntityName_Inserting and EntityName_Updating  partial methods that run on the server. Which is right, but causes concurrency issues, since after saving the client instance of the entity is not updated by the changes made at the server and as soon as you try to save again this will cause concurrency error.
So, what can you do, apart from refreshing after every save which is not very appealing? Update at the client. Not appealing either but at least it can be done elegantly:
Let’s say all entities to implement auditing have 4 fields:
  • DateCreated
  • CreatedBy
  • DateModified
  • ModifiedBy
Add to the Common project a new interface called IAuditable like below:

namespace LightSwitchApplication{
    public interface IAuditable{
        DateTime DateCreated { get; set; }
        string CreatedBy { get; set; }
        DateTime DateModified { get; set; }
        string ModifiedBy { get; set; }
    }
}



Then, also in the common project, add a new class called EntityExtensions:
namespace LightSwitchApplication{
    public static class EntityExtensions{
        public static void Created<TEntityType>(this TEntityType entity, IUser user)
           where TEntityType: IAuditable{
           entity.DateCreated = entity.DateModified = DateTime.Now;
           entity.CreatedBy = enity.ModifiedBy = user.Name;
        }

        public static void Modified<TEntityType>(this TEntityType entity, IUser user)
           where TEntityType: IAuditable{
           entity.DateModified = DateTime.Now;
           entity.ModifiedBy = user.Name;
        }
    }
}



Now let’s suppose your entity’s name is Customer (imagination was never my strong point), the screen’s name is CustomerList and the query is called Customers.

First Viewing the Customer entity in designer click write code and make sure that:
partial class Customer : IAuditable{
}

Then at your screen’s saving method write this:
partial void CustomerList_Saving{
    foreach(Customer customer in this.DataworkSpace.ApplicationData.Details.GetChanges().AddedEntities.OfType<Customer>())
        customer.Created(this.Application.User);
    foreach(Customer customer in this.DataworkSpace.ApplicationData.Details.GetChanges().ModifiedEntities.OfType<Customer>())
        customer.Modified(this.Application.User);
}


This should do it. This way you can also easily move your logic to the server as the interface and extension class are defined in the Common project and they are also available to the server.
 



Thursday, October 6, 2011

Concurrent or fast? I’d rather have both…

Did you know that concurrency provided automatically by LightSwitch might cause performance issues that you cannot easily trace?
LightSwitch uses Entity Framework’s concurrency mechanisms to ensure data consistency while 2 or more users modify the same entries. You can read about it in detail and with examples in this great (as always) post by Michael Washington.
The thing, though, is that using native data sources or SQL server imported data sources, LightSwitch applies concurrency checking to all fields and you can do nothing about it. So, what is wrong about that? The price you have to pay in performance terms is small in exchange to ensuring concurrency, one would say. Unfortunately this is not always the case. Apart from functionality issues that can easily come up (entities with last modification fields for example), there is one special but not so uncommon case that can kill your performance. Large binary fields. Images is the most common example. Checking images byte against byte with every record updated for modifications, is something that, in most cases at least, no one wants.
As in many other cases, RIA comes to the rescue. With RIA services, importing your domain objects in an EF entity model you can fully control which fields are checked for concurrency and which are not. Not only this, but also concurrency exceptions are passed-through to LightSwitch and the resulting behavior is exactly the same as if you were using native or SQL server imported data sources. This is great don’t you think…Winking smile

Wednesday, October 5, 2011

Sort This, you Light of a Switch

Did you know that LightSwitch by default cannot sort or search against lookup columns?
Sad but true. The native Data Grid of LightSwitch cannot sort or search against lookup columns. The good news is that, as always with LightSwitch, you have an option. Which is not at all bad, by the way. In non-editable grids, that is in search or list-detail screens, you can use views. Yes, database views that is. Another solution would be calculated fields, but, although simpler, performance is poor IMHO.
Views? How do I create views in LightSwitch? Well, you don’t. You cannot have views in native data sources (at least I am not aware of some way). But you can import them. Either with a SQL Server data source from an existing database, or with RIA Services data source.
Having a view containing the id of the entity (it doesn’t have to be visible) you can use it to either open the default detail screen on click, or, in the list detail scenario, remove the detail group, add the original entity’s collection query and filter it based on the selected item of the view query, or have a <EntityCollection>_SinlgeOrDefault query and bind the parameter to the view query's selected item id column. Then add a detail group for this query. You might have implementation issues you should deal with, but hey, this is a tips blog.
P.S.1 If you use or planning to use 3rd party controls your commercial data grid might solve this problem without all of the above. But If you don’t…
P.S.2 The whole truth (and nothing but the truth) is that you might have issues correctly importing views from SQL Server (regarding primary key for example, have you fixed it yet George?) so if I have to be honest, I must say RIA is the best way to go…Winking smile