locked
Pass parameter in RIA Service. RRS feed

  • Question

  • Hi Everybody

    I would like to pass parameter in the RIA Service Query.

    In below code you can notice that Invoice Id i am taking mannually in query. i want to make that invoice id dynamic.

    public class ReportTaxGroup
        {
            [Key]
            public string TaxName { get; set; }
            public decimal TaxAmount { get; set; }
         }
    
    
        // TODO: Create methods containing your application logic.
        // TODO: add the EnableClientAccessAttribute to this class to expose this DomainService to clients.
        public class TaxGroupService : DomainService
        {
            private ApplicationDataObjectContext context;
            public ApplicationDataObjectContext Context
            {
                get
                {
                    if (this.context == null)
                    {
                        string connString =
                            System.Web.Configuration.WebConfigurationManager
                            .ConnectionStrings["_IntrinsicData"].ConnectionString;
                        EntityConnectionStringBuilder builder = new EntityConnectionStringBuilder();
                        builder.Metadata =
                            "res://*/ApplicationData.csdl|res://*/ApplicationData.ssdl|res://*/ApplicationData.msl";
                        builder.Provider =
                            "System.Data.SqlClient";
                        builder.ProviderConnectionString = connString;
                        this.context = new ApplicationDataObjectContext(builder.ConnectionString);
    
                    }
                    return this.context;
                }
            }
    
            protected override int Count<T>(IQueryable<T> query)
            {
                return query.Count();
            }
    
            [Query(IsDefault = true)]
            public IQueryable<ReportTaxGroup> GetGroupTaxByInvoice()
            {
                var TaxGroup_1 = this.Context.InvoiceDetails.Where(y => y.Invoice.Id == 2).Select
                    (d => new { TaxName = d.Tax.TaxName , TaxAmount =  (((d.Rate * d.Quantity) * d.Tax.Percentage) / 100) }).AsEnumerable().Select
                    (o => new ReportTaxGroup { TaxName = o.TaxName, TaxAmount = Convert.ToDecimal(o.TaxAmount) }).ToList();
                
                var TaxGroup_2 = this.Context.InvoiceDetails.Where(y => y.Invoice.Id == 2).
                    Select(d => new { TaxName = d.Tax1.TaxName, TaxAmount = (((d.Rate * d.Quantity) * d.Tax1.Percentage) / 100) }).AsEnumerable().
                    Select(o => new ReportTaxGroup { TaxName = o.TaxName, TaxAmount = Convert.ToDecimal(o.TaxAmount) }).ToList();
                
                TaxGroup_1.AddRange(TaxGroup_2);
                
                return TaxGroup_1.AsQueryable().Where(o=>o.TaxName != null).GroupBy(g=>g.TaxName).
                    Select(s=> new ReportTaxGroup { TaxName = s.Key , TaxAmount = s.Sum(sm =>sm.TaxAmount) }).AsQueryable<ReportTaxGroup>();
    
            }
           
        }

    Can anybody please guid me how can i do this ?


    Rashmi Ranjan Panigrahi

    Monday, March 19, 2012 4:26 AM

Answers

  • Just create another query method with a nullable invoiceId parameter in addition to the default one like so:

    [Query(IsDefault = false)] public IQueryable<ReportTaxGroup> GetGroupTaxByInvoice(int? invoiceId) {

    ...your code that does a query using the passed parameter

    }

    Regards


    Xander

    Wednesday, March 21, 2012 7:42 AM

All replies

  • Hi, what do you mean to make the invoice id dynamically? If you would like to get the invoice id from data table, please check this:

    http://lightswitchhelpwebsite.com/Blog/tabid/61/EntryId/47/WCF-RIA-Service-Combining-Two-Tables.aspx


    Wednesday, March 21, 2012 6:45 AM
  • Just create another query method with a nullable invoiceId parameter in addition to the default one like so:

    [Query(IsDefault = false)] public IQueryable<ReportTaxGroup> GetGroupTaxByInvoice(int? invoiceId) {

    ...your code that does a query using the passed parameter

    }

    Regards


    Xander

    Wednesday, March 21, 2012 7:42 AM
  • Xander,

    great tip, Thanx!

    my query is a bit more complex, it needs 4 parameters (product_code, product_color, product_size, quantity)

    it is for apparel industry, it will give back what is needed to manufacture given model of dress (how much material, how long thread, how many zippers, and so on...)

    what client needs is to be able to be able to process MULTIPLE PRODUCTS at the same time, lets say 10-15 articles, each has these 4 parametars...

    do you have ANY idea on how this could be accomplished?

    THANX!

    Tuesday, May 1, 2012 8:44 PM
  • Hi, I may not totally understand your requirement, but nothing stops you from having 4 x parameters (or however many you need) to that method as long as they are all nullable.

    Regards


    Xander

    • Edited by novascape Tuesday, May 1, 2012 9:07 PM
    Tuesday, May 1, 2012 9:06 PM
  • Xander,

    actually, i would (ideally) need something like being able to use "array" of parameters, but i would probably use some transit table.

    to illustrate better - single set of 4 parameters (product_CODE, product_COLOR, product_SIZE, quantity), would be something like this:

    PoloShirt_002, Yellow, XXL, 300 pieces    -   and it will throw me back list of materials that are needed to make those 300 shirts.

    so guys at manufacturing could know how many zippers, fabrics, threads they need to produce those 300 shirts.

    OK, now client wants to make BATCH ORDERS of components, and they want to select multiple products and in multiple quantities,

    like 350 pieces of Yellow XXL shirts, 820 pieces Black M shirts, 1020 pieces brown dresses 36....

    ---

    just wondering if there's a way of passing this in a kind of array?

    probably asking too much :)   my guess is that i will have to use some go-between table, with batch order lines...

    BUT - just wanted to ask, it would be good to know if this is actually possible.

    THANKS to everyone, really great forum here!!!


    Tuesday, May 1, 2012 11:15 PM
  • Could you define a class containing the product_CODE, product_COLOR, product_SIZE &  quantity values, call it something like OrderLine, and then have a variable defined as List(Of OrderLine)? You could then pass this List(Of OrderLine) variable as your parameter.

    Simon Jones
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, please remember to "Mark as Answer". This will help other people find answers to their problems more quickly.

    Wednesday, May 2, 2012 7:29 AM
  • Simon,

    YES, something like that, if that might be feasable?

    do you know of any examples, or exact syntax in VB i could try?

    also - when using "array" parameters (List), will i have to use some kind of loop to process each line of parameters, or will it do aggregations on it's own?

    Wednesday, May 2, 2012 8:00 AM
  • List(Of T) variables have Add methods to add items and you can use For Each to iterate through them. Yes, aggregations are possible too.  

    Public Class OrderLine
        Public Property ProductCode As String
        Public Property ProductColor As String
        Public Property ProductSize As Integer
        Public Property Quantity as Integer
    End Class
    
    Dim Orders as New List(Of OrderLine)
    Orders.Add(New OrderLine With {.ProductCode = "thing", .ProductColor = "red", .ProductSize = 12, .quantity = 2})

    
    


    Simon Jones
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, please remember to "Mark as Answer". This will help other people find answers to their problems more quickly.

    Wednesday, May 2, 2012 8:21 AM
  • Some other options springing to mind if you want it to be truly generic are:

    1) define a string parameter and use an XML fragment to pass your list of property names and values or concoct your own JSON-like format or whatever format you can easily write and parse OR

    2) define a byte[] parameter and pass a serialized Dictionary object using the SilverlightSerializer from Mike Talbot at http://whydoidoit.com

    Regards


    Xander

    Wednesday, May 2, 2012 8:28 AM
  • Simon,

    THANK YOU, that would be fantastic, i just need to give it a try.

    parameter list is to be passed to WCF RIA query, so i hope it's possible to add this like property to the screen, for being able to link it as parametere to the query?

    ugh that would be awesome!

    Wednesday, May 2, 2012 8:38 AM
  • I suspect that LS might not import a RIA service query method containing a parameter that is a complex data type, although I've not verified that?

    Xander

    Wednesday, May 2, 2012 8:43 AM
  • Indeed, I do not know if this method will be useable in this precise situation. There should be no problem if you are just passing the data within one project or between referenced projects but there may be restrictions if you are using some other defined interface.

    Simon Jones
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, please remember to "Mark as Answer". This will help other people find answers to their problems more quickly.

    Wednesday, May 2, 2012 8:51 AM
  • Mind you, the SilverlightSerializer mentioned above should be able to serialize Simon's suggested data structure, allowing you to pass that as a byte[] as well, so that would be yet another option.

    Regards


    Xander

    • Edited by novascape Wednesday, May 2, 2012 8:57 AM
    Wednesday, May 2, 2012 8:56 AM
  • Simon,

    THANX!

    i will try this and post working results.

    just one thing - if parameter is List of Class (multriple lines), how do i define input parameter inside WCF RIA?

    just as single parameter, or like 4 parameters (if class has 4 properties?)

    Thanks again!

      

    Wednesday, May 2, 2012 11:51 AM
  • You would define it in the same way - a single parameter As List(of T).

    Whether you define your Class in the RIA Service or in the main application is debateable. I'd probably try it in the RIA Service first. It can then be consumed in your main application.

    This is pretty much as suck it an see approach. I can't guarantee that you will be able to get it to work without serializing/unserializing - IE using JSON or some other approach.


    Simon Jones
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, please remember to "Mark as Answer". This will help other people find answers to their problems more quickly.

    Wednesday, May 2, 2012 11:57 AM
  • Simon & Xander,

    Thanks for pointing me towards solution, i'll post my results, once everything works :)

    THANX!

    Wednesday, May 2, 2012 12:01 PM
  • Simon,

    do you know how could i import that Class to the LightSwitch screen, so i could bind it as parameter for RIA query?

    hmmm that might be a tricky one? :)

    Wednesday, May 2, 2012 1:50 PM
  • If you make the OrderLine class Public in your RIA service and you have a reference to that project in your main application then you should have no problem in declaring a parameter As List(Of OrderLine).

    (You will probably have to fully qualify the name of the class: "As List(Of RIAServiceName.OrderLine)" giving the name of the RIAService project.)

    List(Of T), when fully qualified, is System.Collections.Generic.List(Of T), if you didn't already know.


    Simon Jones
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, please remember to "Mark as Answer". This will help other people find answers to their problems more quickly.

    Wednesday, May 2, 2012 1:58 PM
  • sorry, i got it working... :)

    for simple parameters and i will move from there

    the thing is:

    1. MAKE PARAMETER NULLABLE, otherwise it will not work   (can String be Nullable)?

    2. you must have default query quithout parameters - and LS will import it like TABLE.   Queries with parameters will be imported as Queries, i find this pretty smart!

    GREAT!

    Wednesday, May 2, 2012 2:37 PM
  • Simon, sorry for being such a pest... :)

    i got parameter like this to work great -- "orderline123 As System.Nullable(Of Integer)" 

    but when i define parameter like -- "orderline123 As List(Of OrderLine)" - it will not import it as query when updating datasource...

    i guess it needs to be made Nullable?    can i make List of Public Class Nullable?

    Thanx!

    Wednesday, May 2, 2012 3:12 PM
  • The problem is more likely to be the use of a complex type rather than the lack of nullability. If complex types are not useable directly you'd have to serialize the parameter (as a string or as an array of byte) to pass it.

    Simon Jones
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, please remember to "Mark as Answer". This will help other people find answers to their problems more quickly.

    Wednesday, May 2, 2012 3:45 PM
  • Simon,

    THANX, i will try that...

    but - when it accepts serialized parameter, do You have any idea what kind of property will it import into Screen to be binded with Query?

    i.m. will it accept this, as it now only shows String, Integer, Money, Date and so on?   i am talking about Screen in LS where i will define value for property that is binded to Query?

    THANKS AGAIN!

    Wednesday, May 2, 2012 3:48 PM
  • If you serialize to pass a parameter you are responsible for unserializing it back to the correct format again. What you do with it after that is up to you and the format of the data.

    I think you may be trying to run before you can walk and you're in danger of designing something that is way too complicated. LightSwitch Query parameters are designed to be simple things such as an ID number or a string, not a list of various, related values. If all these values were stored in the database as OrderLines, you could pass the single OrderID to your RIA Service. I'm sure I've suggested something like this elsewhere.


    Simon Jones
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, please remember to "Mark as Answer". This will help other people find answers to their problems more quickly.

    Wednesday, May 2, 2012 4:06 PM
  • Simon,

    yes, that is the way to go, Kostas also had this same approach couple of days ago.

    i just wondered if something Sci-Fi like Class (array of parameters) could work out of the box, but it is not a must.

    important is that i got it working and it's doing the aggregation like it should.

    THANKS for clarifying this in such detail, now we know what is the way to go.

    Wednesday, May 2, 2012 4:13 PM
  • On this same topic. When I add a RIA service to my project and create a search screen it displays a result set. When I then enable a property as a link and open the default screen for the entity I assume its passing the Key to my RIA service to return that entity? In my case the Key is a string. If i add a Key parameter described above will that allow me to access the Key being passed?

    Steve

    Tuesday, September 24, 2013 7:18 PM
  • @Steve : the answer is no, not that I have been able to find. If you want access to the key inside the RIA domain service you will have to add a separate non-default query method with a nullable key parameter to have access to that key inside the query method.

    Regards, Xander. My Blog

    Wednesday, September 25, 2013 1:21 AM