LLBLGen with ServiceStack.net

Posts   
 
    
scotru
User
Posts: 104
Joined: 16-Feb-2006
# Posted on: 06-Mar-2013 19:01:02   

Anyone using LLBLGen Pro with ServiceStack.NET (http://servicestack.net/)? Particularly I'd love to see some templates aimed at this and/or discussion of best practices or lessons learned.

Thanks!

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 07-Mar-2013 06:35:49   

I never used ServiceStack and it looks like no info on the forum either. What I can see on the site is that they have different products (ServiceStack.Text, OrmLite, Redis and Catching). What do you like to use in LLBLGen?

If you want DTO's, you see/modify those custom templates: http://llblgen.com/TinyForum/Messages.aspx?ThreadID=13256

Everything else could be provided by LLBLGen/NHibernate/EF vs. that ORMLite. BTW they don't show LLBLGen Framework on their benchmarks.

Now, if you really like it, you could make your own templates to support it. You even could make your own additional framework on LLBLGen Designer. For more info see the SDK docs: http://llblgen.com/documentation/3.5/SDK

David Elizondo | LLBLGen Support Team
scotru
User
Posts: 104
Joined: 16-Feb-2006
# Posted on: 07-Mar-2013 08:52:14   

Hey David,

Thanks for responding. These are good questions, let me elaborate more on my goals and reasons for looking at ServiceStack. First, for background, a nice explanation of ServiceStack's raison d'etre by it's creator can be found here: http://stackoverflow.com/questions/9699083/servicestack-vs-asp-net-web-api and here: https://github.com/ServiceStack/ServiceStack/wiki/Advantages-of-message-based-web-services

I don't want to use OrmLite. I like LLBLGen's ORM much better (and NHibernate would likely be my second choice, for which I would still use the LLBLGen designer). Particularly I want database independence on the backend--which I get with LLBLGen/Adapter. ServiceStack can be used with other ORMs as demonstrated here with NHibernate: http://www.philliphaydon.com/2012/06/using-nhibernate-with-servicestack/

What am I looking to get/use out of ServiceStack?

1) I want to be able to run on Mono. 2) I need to be able to consume the services on a variety of .NET platforms (MonoTouch, Mono for Android, ASP.NET MVC, WPF, and WinForms). Some of these platforms do not appear to support the LLBLGen Runtimes. (Otherwise I'd just as soon pass LLBLGen Entities rather than DTOs) 3) I like the idea of transport independence (XML, JSON, SOAP..) all supported out of the box and the ability to extend new transports easily. 4) I like the message based architecture in SS vs. the method based architecture in traditional WCF:

(ServiceStack):
class Customers
{
    public List<int> Ids { get;set; }
    public List<string> UserNames { get;set; }
    public List<string> Emails { get;set; }
}
class CustomersResponse
{
    public List<Customer> Results { get;set; }
}

(WCF) Traditional
[ServiceContract]
class MyWebServices : IWebServices
{
  Address GetCustomerAddress(int customerId);
  CustomerInfo GetCustomerInfoByUserNames(string userName);
  List<Customer> GetCustomersByIds(List<int> customerIds);
}

5) Performance.

So, in summary, I'm looking to create REST-ful services that encapsulate the business logic and data access layer for a variety of thin user interface clients on a variety of platforms.

I've looked at Matt Cowan's very cool ServiceStack wrapper for LLBLGen--but it requires the LLBLGen run times on all client platforms: http://www.mattjcowan.com/funcoding/2012/12/12/service-based-data-adapter-for-llblgen-entities-using-servicestack/ What I want is ServiceStack on top of the LLBLGen Run-time, not underneath it.

I'm considering using LLBLGen to get me started with some code-gen by scaffolding my REST-ful service templates:

A quick overview of doing REST-ful services with ServiceStack is here: https://docs.google.com/presentation/d/1BHV5luhRY3pg7hu0tdQNrwgZd7nOISCHKAEGuQJ48Vk/present#slide=id.i0

This code is from one of ServiceStack's examples and is the kind of scaffolding that I was thinking about templating (except using LLBLGen instead of the repo):



//Web Service Host Configuration
public class AppHost : AppHostHttpListenerBase
{
    public AppHost() : base("TODOs Tests", typeof(Todo).Assembly) {}

    public override void Configure(Container container)
    {
        container.Register(new TodoRepository());
    }
}

//REST Resource DTO
[Route("/todos")]
[Route("/todos/{Ids}")]
public class Todos : IReturn<List<Todo>>
{
    public long[] Ids { get; set; }
    public Todos(params long[] ids)
    {
        this.Ids = ids;
    }
}

[Route("/todos", "POST")]
[Route("/todos/{Id}", "PUT")]
public class Todo : IReturn<Todo>
{
    public long Id { get; set; }
    public string Content { get; set; }
    public int Order { get; set; }
    public bool Done { get; set; }
}

public class TodosService : Service
{
    public TodoRepository Repository { get; set; }  //Injected by IOC

    public object Get(Todos request)
    {
        return request.Ids.IsEmpty()
            ? Repository.GetAll()
            : Repository.GetByIds(request.Ids);
    }

    public object Post(Todo todo)
    {
        return Repository.Store(todo);
    }

    public object Put(Todo todo)
    {
        return Repository.Store(todo);
    }

    public void Delete(Todos request)
    {
        Repository.DeleteByIds(request.Ids);
    }
}

I'll definitely check out the DTO templates you posted.

I appreciate any and all feedback. If I can simplify this by doing more with LLBLGen and less with ServiceStack, I'm definitely open to that.

Basically I was hoping to find someone who had played with some of these combinations already and might be able to give me some suggestions/guidance. I've used older versions of LLBLGen quite a bit but only in monolithic UI based apps that tied directly to the database. So SOA is new to me, and I'm trying to find an architecture that will be good for long term maintainability.

Thanks!

raist
User
Posts: 114
Joined: 19-Apr-2010
# Posted on: 08-Mar-2013 22:18:54   

From my own experience. You could use Llblgen to create your own set of templates for ServiceStack (or JSON, or WCF or whatever). Llblgen is a good ORM with a great designer, but also a quite powerful templating system (much better than T4, for example). In your code example you only need to take care of names and types on entities and field and plug them to the DTOs. If you give an small example on Northwind with the desired code result , maybe I can provide a matching starting template (We'd be interested in templates to produce multi-format services too).

Running Llblgen on Mono... well I'm not the one answering that, but I think it's a completely different task stuck_out_tongue_winking_eye

MJC
User
Posts: 50
Joined: 06-May-2004
# Posted on: 11-Mar-2013 05:48:15   

I had no idea others were interested in ServiceStack and I just saw this question here on the forum. I've been using ServiceStack for a while on various projects, and in my SharePoint projects as well.

This week and last, I've worked really hard in the evenings (after my day job consulting) and into the late night hours to get some templates put together to combine LLBLGen and ServiceStack. I just published a post, see it here:

http://www.mattjcowan.com/funcoding/2013/03/10/rest-api-with-llblgen-and-servicestack/

You can see a full blown demo of a UI and the REST services at work with ServiceStack as the service layer and LLBLGen doing all the CRUD magic here:

http://northwind.mattjcowan.com

Follow the GitHub links to get to the source code and the templates.

Let me know if this is useful, it's been a lot of fun to build!

scotru
User
Posts: 104
Joined: 16-Feb-2006
# Posted on: 11-Mar-2013 08:54:06   

Wow! smile I haven't had time to look into this in much detail but at first glance, these look incredible! Really nice work here, this looks like exactly what I've been looking for. I'm going to review in more detail this week--but I think these are going to be a huge help to me. I think I've found your Amazon wish list--is it up date? smile

scotru
User
Posts: 104
Joined: 16-Feb-2006
# Posted on: 11-Mar-2013 09:00:45   

Raist,

It looks like Matt has beaten us to the punch on templates smile As for LLBLGen on Mono, I haven't tried the most recent versions, but 2.6 was working without problems for me on Mono 2. So I'll give 4.0 a try on Mono 3 once it comes out in a few weeks and report my results (maybe by trying to host a copy of Matt's demo on Mono).

raist
User
Posts: 114
Joined: 19-Apr-2010
# Posted on: 11-Mar-2013 09:32:34   

Wow!!! It really seems tasty "One template set to rule them all" stuck_out_tongue_winking_eye I'll look through it this week, but seems REALLY interesting.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39568
Joined: 17-Aug-2003
# Posted on: 11-Mar-2013 12:52:19   

Matt has answered this question with a better answer than I ever could have come up with. Amazing work! simple_smile

Frans Bouma | Lead developer LLBLGen Pro
MJC
User
Posts: 50
Joined: 06-May-2004
# Posted on: 11-Mar-2013 15:40:33   

@scotru - If you do get the source to work hosted on Mono (nginx?), let me know what changes you had to make to make it work (if any, I'm assuming there might be a few). Feel free to make or suggest updates to the templates.

raist
User
Posts: 114
Joined: 19-Apr-2010
# Posted on: 15-Mar-2013 10:49:30   

On functionality. Of course you could add more visualization formats (Excel, PDF, ReportView, etc.), but I see more value in improving the querying capabilities. Let me try to explain my view. In general there are three query levels: Relational schema -> Tree (usually a graph) -> Plain view

  1. If you can query the relational schema, you get SQL or this new lovely ad-hoc quering tools like QLinkView, Tableau or Quiterian. Too hard to develop
  2. If you can create a tree to query it you get part of an ORM/DataSet, with relations and prefetchs... but we are happy Llblgen users, so no easy gain here, but you could write lovely LDAP-like queries (Netscape used to support it, but I havent tried in the last 10 years stuck_out_tongue_winking_eye ):
#  all users but andy from all ous except those in the R&D and HR containers:
(&(!(|(ou:dn:=ResearchAndDevelopment)(ou:dn:=HumanResources)))(objectClass=person)(!cn=andy))

  1. To query a plain view. We have two point to develop: "view" and "query" VIEW (with distinct names):
  2. Entities (with or without forf)
  3. TypedViews (mapped to table/view, but also to SP and TVF (new!!!))
  4. TypedLists
  5. Named DynamicQueries (can be generated from a Factory and post-filtered) QUERY = filters (plain: no relations or prefetchs. include/exclude?) + sorting (field + direction)
  6. On resultset fields
  7. On parameters (for SP and TVF)
  8. On additional conditions (example: on authorization role)

On the technical part If you wish to advance through the third option (plain view), we have followed that path for standard ASP.Net templates. We are using two things: 1. "SuperBucket". It includes: - RelationPredicateBucket - SortField - SortDirection - Parameters (for SP & TVF) - SpPredicates (for SP web server post-filtering. It creates Linq.Expression<Func<TRow, bool>> to filter the resultset AFTER you call the SP and get the data from the database) - ObjectDescriptor: name, mappingType, etc. of the associated object (entity, TL, TV, Query) 2. SecurityProfileFilter. It is a SuperBucket generated with the (role, userId) dupla. Either sets the value (ex. SP parameters) or add additional conditions (predicate.AddWithAnd(...))

We're really open to sharing.

Regards.

MJC
User
Posts: 50
Joined: 06-May-2004
# Posted on: 19-Mar-2013 21:52:48   

Hey Raist,

Sorry, didn't see your post until now. Great ideas.

Converting to a Linq.Expression sounds pretty cool. For now, I'm just sticking to the LLBLGen adapter query conventions, but I agree that would be nice, do you have something done like that? The LDAP type query for filters is working out pretty nicely in my situation, for these GET url requests (trying to keep it RESTful was the goal), but you could create objects and pass them with posts, is that what you're referring to?

1) Missing still in this implementation are filters on the "includes" (i.e.: prefetches, only implemented "limit" right now). I do have filters on relations, so you can return only products where orderdetails and/or orders for example meet a criteria, but I don't have filters within the prefetch elements yet where one could return products with related orderdetails, with only the orderdetails and orders that match a condition for example. Shouldn't be too hard to implement, since the filtering logic is there, just need to add it to the included items as well.

2) Also aggregates (sum, avg, min, max, etc...), and complex relational queries that demand relationship aliases.

3) Then finally, as you mentioned, stored proc support, typed lists, and typed views. That would be neat.

4) Other stuff like authorization, validation, boy, seems like that one could be endless, would probably prefer to just allow hooks to be added to the generated code at that point. A "SecurityProfileFilter" seems neat for sure. But then, there could be any number of filters that could meet use-cases.

Maybe at that point, we start having conventions for using properties in the designer to control the output. Does that make sense?

raist
User
Posts: 114
Joined: 19-Apr-2010
# Posted on: 20-Mar-2013 10:52:45   

Converting to a Linq.Expression sounds pretty cool. For now, I'm just sticking to the LLBLGen adapter query conventions, but I agree that would be nice, do you have something done like that?

It really makes me feel a little bit dirty, as it is web-server side filtering (handle with care). I could only find its use case with SP mapped typedviews. It is the equivalent to entity projections. Standard adapter queries should be ok in most cases. I'll post the code.

The LDAP type query for filters

Its main functionality to clone on a REST interface is the hability to query on related entities (ej. person on OrganizationalUnit). If you have this functionality already implemented, then it's the second time you code faster than we can propose ideas smile

I do have filters on relations

Yes, definitely it's the second time.

Prefetches are not about filtering (for that we have relations). They are about the returned resultset. If you want to support prefetches it is like suporting a dataset instead of a datatable. I would separate the dataset definition from the quering: a) Static coded, named. Ex. ProductWithOrderDetails (named query, no big deal here) b) Dynamic. You need the client to send a request with the dataset definition (prefetches, include/exclude fields). Uff, I think I would use a POST that for, but then there are two related queries from the same client -> state management required, not so much REST

Also aggregates (sum, avg, min, max, etc...), and complex relational queries that demand relationship aliases

We use typedlists for that, supporting expression defined fields. But they are static (generated code).

Other stuff like authorization, validation, boy, seems like that one could be endless

Why? Validation must be static (the specific value of a field in the same context is ALWAYS valid or NEVER), it can be done at the ORM level if wished. Authorization is just what I told you: public static Bucket GetRoleFilter(string roleName, ProfileEntity profile) The limiting stuff here, I think, is that you need to get the userId, and the (userId, roleName, profileParameters) from somewhere, and that is implementation specific. But hey!!! you are creating a framework, so you do not need to take care of that. stuck_out_tongue_winking_eye (the profileParameters are the ones you use to filter. ex. CustomerId)

Maybe at that point, we start having conventions for using properties in the designer to control the output. Does that make sense?

Definitely. We make heavy use of Custom PropertiesFrameworkSettings, but we still use a XML configuration file for multivalued properties (ex. in an entity you need a role filter for each role; or in a typedlist you can have several calculated fields). I DO NOT like it, but IMOO it is better than the actual designer alternative. Maybe if we could think about some conventions as you propose... Frans, are you listening? wink

I think the big question is the scope of your project. Is it going to be a quering front-end for server defined "entities" (entities, TL, TV, named queries) or a dynamic entities (tree-like) generator too?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39568
Joined: 17-Aug-2003
# Posted on: 20-Mar-2013 11:16:48   

Definitely. We make heavy use of Custom Properties, but we still use a XML configuration file for multivalued properties (ex. in an entity you need a role filter for each role; or in a typedlist you can have several calculated fields). I DO NOT like it, but IMOO it is better than the actual designer alternative. Maybe if we could think about some conventions as you propose... Frans, are you listening?

simple_smile

There's an alternative in the designer: frameworksettings! It's the best way to do this. You define custom frameworksettings files with your own settings, in an xml fashion, which are then usable inside the designer. You can then set the settings per element, or if you use defaults, using defaults at the project level. You can utilize the bulk setting editor in the designer to set settings in bulk and you can read them easily in a template to control your output. See the SDk docs for details, and also e.g. the NHibernate templates for examples how they're used in practice simple_smile

Custom properties are brittle, use the framework settings, as they're more flexible and you don't need an external file during code generation simple_smile

Frans Bouma | Lead developer LLBLGen Pro
raist
User
Posts: 114
Joined: 19-Apr-2010
# Posted on: 20-Mar-2013 11:33:02   

Linq expressions filtering code enclosed. Use case: TypedView post filtering on the webserver side (ex. SP mapped) Description: Generates a list of serializable predicates (SpTypedViewPredicate) that later are compiled (with (SpTypedViewUtils<TRow>) to generate the Linq Expression (Expression<Func<TRow, bool>>)

Included: - Filter generation example. - TypedView usage example - The filter factory code (SpTypedViewPredicate) and the PredicateExpression generator (SpTypedViewUtils<TRow>)

Comments welcomed.

Attachments
Filename File size Added on Approval
SP_LinqExpressions.zip 5,198 20-Mar-2013 11:33.54 Approved
raist
User
Posts: 114
Joined: 19-Apr-2010
# Posted on: 20-Mar-2013 12:21:00   

Of course FrameworkSettings are the prefered alternative!!! flushed Example:

<settingDefinition name="DescriptiveField"
    description="The name of the field whose value will be shown in the references to related entities instead of the actual FK value."
    canBeEmpty="true" category="ASP.Net GUI Templates" type="string" targetElement="2" />
<settingDefinition name="ShowTheseMnRelatedEntitiesAsMultipleSelect"
    description="Comma separated list of M_N related entities. In the edit and insert forms of the current entity, the indicated entities can be directly selected through a ListBox."
    canBeEmpty="true" category="ASP.Net GUI Templates" type="string" targetElement="2" />

... but I still feel they are not so convenient for multivalued parameters: comma separated list?? disappointed

We use CustomProperties only for object specific parameters (example: SPCall parameters: "DefaultEndingDate", etc.) Here, we use ad-hoc conventions (Default<ParameterName>), but use cases are so open I do not see how to normalize this.

To map the following structure I have not found an alternative to a XML file

<EntityFilter Entity="Order">
    <Role Name="Employee">
        <RoleFieldMap EntityField="EmployeeId" ProfileField="EmployeeId" />
    </Role>
    <Role Name="Customer">
        <RoleFieldMap EntityField="CustomerId" ProfileField="CustomerId"/>
    </Role>
    <Role Name="Supplier">
        <RoleFieldMap EntityField="Product.SupplierId" ProfileField="SupplierId"
            Relation="Order.OrderDetails > OrderDetail.Producto" />
    </Role>
    <Role Name="Shipper">
        <RoleFieldMap EntityField="ShipVia" ProfileField="ShipperId"/>
    </Role>
</EntityFilter>

... or

      <EntityDefinition Name="OrderDetail">
        <CalculatedFields>
            <CalculatedField Name="Total" Type="System.Decimal" Aggregate = "Sum"
                Value="OrderDetailFields.Quantity * OrderDetailFields.UnitPrice" />         
            <CalculatedField Name="Average" Type="System.Decimal" Aggregate = "Avg"
                Value="OrderDetailFields.Quantity * OrderDetailFields.UnitPrice" />         
        </CalculatedFields>
        <SearchRelatedFields>
            <SearchRelatedField Name="Customer.Country" Relation="OrderDetail.Pedido > Order.Client"/>
            <SearchRelatedField Name="Supplier.CompanyName" Relation="OrderDetail.Producto > Product.Supplier"/>
        </SearchRelatedFields>
      </EntityDefinition>

By the way... following, the generated code for the previous role filtering definition. Not such a big deal, is it?

PredicateExpression userFilter = new PredicateExpression();
RelationCollection userRelations = new RelationCollection();
Predicate filterPredicate = null;

switch(_data.RolType)
{
    case RoleType.Employee:
        EmployeeProfileEntity currentEmployeeProfile = (EmployeeProfileEntity)_data.BaseProfile;
        filterPredicate = (OrderFields.EmployeeId == currentEmployeeProfile.EmployeeId);
        break;
    case RoleType.Customer:
        CustomerProfileEntity currentCustomerProfile = (CustomerProfileEntity)_data.BaseProfile;
        filterPredicate = (OrderFields.CustomerId == currentCustomerProfile.CustomerId);
        break;
    case RoleType.Supplier:
        SupplierProfileEntity currentSupplierProfile = (SupplierProfileEntity)_data.BaseProfile;
        userRelations.AddRange(OrderEntity.GetRelationsForNavigator("OrderDetails"));
        userRelations.AddRange(OrderDetailEntity.GetRelationsForNavigator("Producto"));
        filterPredicate = (ProductFields.SupplierId == currentSupplierProfile.SupplierId);
        break;
    case RoleType.Shipper:
        ShipperProfileEntity currentShipperProfile = (ShipperProfileEntity)_data.BaseProfile;
        filterPredicate = (OrderFields.ShipVia == currentShipperProfile.ShipperId);
        break;
    default:
        break;
}
if (filterPredicate != null)
    userFilter.Add(filterPredicate);

NOTE: I forgot, to use role-based filtering you need a place to store userProfile parameters too (the parameters used to filter)

arzulfi
User
Posts: 2
Joined: 22-Dec-2018
# Posted on: 22-Dec-2018 08:23:56   

Hi, Just tried to use Matt's templates with trial version with no luck. Even tried to generate code from Github sample but Matt's template is not showing on code generation window.

Apparently, it seems that templates need to be updated. Just wondering, if somebody can do it!

arzulfi
User
Posts: 2
Joined: 22-Dec-2018
# Posted on: 22-Dec-2018 18:52:39   

Fantastic, it is working perfectly now.