- Home
- LLBLGen Pro
- Custom Templates
LLBLGen with ServiceStack.net
Joined: 16-Feb-2006
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!
Joined: 28-Nov-2005
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
Joined: 16-Feb-2006
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!
Joined: 19-Apr-2010
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
Joined: 06-May-2004
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!
Joined: 16-Feb-2006
Wow! 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?
Joined: 16-Feb-2006
Raist,
It looks like Matt has beaten us to the punch on templates 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).
Joined: 19-Apr-2010
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
- 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
- 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 ):
# 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))
- To query a plain view. We have two point to develop: "view" and "query" VIEW (with distinct names):
- Entities (with or without forf)
- TypedViews (mapped to table/view, but also to SP and TVF (new!!!))
- TypedLists
- Named DynamicQueries (can be generated from a Factory and post-filtered) QUERY = filters (plain: no relations or prefetchs. include/exclude?) + sorting (field + direction)
- On resultset fields
- On parameters (for SP and TVF)
- 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.
Joined: 06-May-2004
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?
Joined: 19-Apr-2010
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
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. (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?
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?
Joined: 17-Aug-2003
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?
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
Custom properties are brittle, use the framework settings, as they're more flexible and you don't need an external file during code generation
Joined: 19-Apr-2010
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.
Filename | File size | Added on | Approval |
---|---|---|---|
SP_LinqExpressions.zip | 5,198 | 20-Mar-2013 11:33.54 | Approved |
Joined: 19-Apr-2010
Of course FrameworkSettings are the prefered alternative!!! 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??
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)
Joined: 22-Dec-2018
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!
Joined: 17-Aug-2003
You likely have to adjust the .net versions, e.g. here: https://github.com/mattjcowan/LLBLGenPro_SS_Api_Razor_Templates/blob/master/llbl/Templates/MJC.TemplateBindings.ServiceStack.templatebindings#L4
The minimum .NET version is .NET 4.5.2