Blog on development in general, and specifically on .NET
When using Entity Framework, you cannot perform date/time operations as you would normally do in .NET/LINQ to Objects. For instance, the following query throws an exception:
For a full description of DateDiff’s first parameter, refer to http://msdn.microsoft.com/en-us/library/ms189794.aspx.
If you want to achieve the same result, that is, return a TimeSpan, you need to use LINQ to Objects at the end:
Recently, the NHibernate team released NH 4.0. You can get it as a NuGet package from https://www.nuget.org/packages/nhibernate, as a ZIP from http://sourceforge.net/projects/nhibernate/ or as source code from https://github.com/nhibernate/nhibernate-core. The full release notes are available at https://github.com/nhibernate/nhibernate-core/blob/master/releasenotes.txt, but here are some highlights.
One of its most important features is that it no longer needs Iesi.Collections for most common uses: where you would declare a set as Iesi.Collections.Generic.ISet<T>, now you use System.Collections.Generic.ISet<T>. However, if you want to use the order-by attribute of sets, you still need Iesi.Collections, because NHibernate will still use it (LinkedHashSet<T>). All of the public APIs that used Iesi.Collections.Generic.ISet<T> or Iesi.Collections.ISet now use System.Collections.Generic.ISet<T>, this includes all the event handler methods.
Method SaveOrUpdateCopy of ISession was removed and Merge should be used instead.
The ManagedWebSessionContext context class was removed and the managed_web alias for XML configuration is no longer supported. Now you should use WebSessionContext and web.
The Firebird driver was removed and replaced for FirebirdClientDriver. ASA10ClientDriver, ASAClientDriver and SQLiteDriver were removed in favor of SybaseSQLAnywhereDriver, SybaseAsaClientDriver and SQLite20Driver, respectively. A managed ODP.NET driver for Oracle is now available (OracleManagedDataClientDriver).
Sql2012Dialect was introduced and now properly pages records. Also added Ingres9Dialect. SybaseASADialect (use SybaseSQLAnywhere10Dialect),
MySQL now supports batching inserts (MySqlClientBatchingBatcher).
There have also been some breaking changes in the IProjection interface because the IEnhancedProjection interface was removed and its methods moved to IProjection.
Misspelled class AdoNetWithDistrubtedTransactionFactory is now AdoNetWithDistributedTransactionFactory.
NHibernate XML configuration on App.config or Web.config now accepts attribute linqtohql.generatorsregistry.
On mapping by code, you can now specify the class of a one-to-one endpoint (IOneToOneMapper.Class) and an optional table check clause (IClassMapper.Check). Also available are enhanced id generators Enhanced Sequence (Generators.EnhancedSequence) and Enhanced Table (Generators.EnhancedTable). You can now pass a dictionary to IGeneratorMapper.Params, no need to use anonymous types, which is better for dynamic code.
QueryOver projections now support Math.Round() to round up floating point numbers.
DefaultIfEmpty is now supported with GroupBy and Distinct is now supported with anonymous types.
Finally, all static type fields in NHibernateUtil are now declared as their exact type, not a base class, which is better for using in mapping by code.
ASP.NET includes a valuable yet not well known extension point called the page parser filter. I once briefly talked about it in the context of SharePoint, but I feel a more detailed explanation is in order.
A page parser filter is a class with a public parameterless constructor that inherits from PageParserFilter and is registered on the Web.config file, in the pages section, pageParserFilterType attribute. It is called when ASP.NET is compiling a page, the first time it is called, for every page. There can be only one page parser filter per web application.
Why is it a parser? Well, it parses – or, better, receives a notification for - every control declared on the markup of a page (those with runat=”server” or contained inside of), as well as all of the page’s directives (<%@ … %>). The control declarations include all of its attributes and properties, the recognized control type and any complex properties that the markup contains. This allows us to do all kinds of crazy stuff:
- Inspect, add and remove page directives;
- Setting the page’s compilation mode;
- Insert or remove controls or text literals dynamically at specific places;
- Add/change/remove a control’s properties or attributes;
- Even (with some reflection magic) change a control’s type or tag.
So, how do we all this? First, the parser part. We can inspect all page directives by overriding the PreprocessDirective method. This is called for all page directives:
The page’s compilation mode is controlled by GetCompilationMode:
As for adding controls dynamically, we make use of the ParseComplete method:
Same for changing a control’s properties:
And even changing the control’s output tag or instance type:
Why would we want to change a control’s type? Well, thing about generics, for once.
And now the filtering part: why is it a filter? Because it allows us to filter and control a number of things:
- The allowed master page, base page class and source file;
- The allowed controls;
- The total number of controls allowed on a page;
- The total number of direct and otherwise references on a page;
- Allow or disallow code and event handler declarations;
- Allow or disallow code blocks (<%= … %>, <%: … %>, <% … %>);
- Allow or disallow server-side script tags (<script runat=”server”>…</script>);
- Allow, disallow and change data binding expressions (<%# … %>);
- Add, change or remove event handler declarations.
All of the filtering methods and properties described below return a Boolean flag and its base implementation may or may not be called, depending on the logic that we want to impose.
Allowing or disallowing a base page class is controlled by the AllowBaseType method (the default is to accept):
For master pages, user controls or source files we have the AllowVirtualReference virtual method (again, the default is true):
Controls are controlled (pun intended) by AllowControl, which also defaults to accept:
This may come in handy to disallow the usage of controls in ASP.NET MVC ASPX views!
The number of controls and dependencies on a page is defined by NumberOfControlsAllowed, NumberOfDirectDependenciesAllowed and TotalNumberOfDependenciesAllowed. Interesting, the default for all these properties is 0, so we have to return –1:
Direct dependencies are user controls directly declared in the page and indirect ones are those declared inside other user controls.
Code itself, including event handler declarations, are controlled by AllowCode (default is true):
If we want to change a data binding expression, we resort to ProcessDataBindingAttribute, which also returns true by default:
For intercepting event handlers, there’s the ProcessEventHook, which likewise returns true by default:
And finally, for code blocks, server-side scripts and data binding expressions, there’s the ProcessCodeConstruct method, which likewise also allows everything by default:
This was in no means an in-depth description of page parser filters, I just meant to give you an idea of its (high) potential. It is very useful to restrict what end users can place on their pages (SharePoint style) as well as for adding dynamic control programmatically in specific locations of the page, before it is actually built.
As usual, let me hear your thoughts!
Like Entity Framework Code First Succinctly, this book has something for the beginner as well as for more advanced users. Unlike EFCFS, it covers the current version of NHibernate.
My good friend Zoran Maksimovic (@zoranmax) was the technical reviewer and besides him, I also want to thank everyone at Syncfusion: Hillary Bowling, Darren West, Tres Watkins and Graham High for their feedback and support, and for the opportunity they gave me. Of course, my coleagues at Critical, Pedro Gomes (@pedromvgomes) and Marco Carreira, and also my old friend Tiago Andrade, who also conducted reviews, cannot be forgotten as well!
Go ahead, grab your copy and let me know what you think!
By the way, it might be interesting to write something about my experience as an author… Any of you Succinctly authors out there would like to share your experience? Write me a line or comment here! Thanks!
SharePoint Designer 2013 workflows brought along new and quite welcome features. I will list my favorite ones.
First, the ability to define stages (blocks of instructions) and to jump (yes, goto-style!) between them. This permits a better organization of our code and because of conditional jumps, even includes the ability to reuse code and to loop between stages.
Next one is stage-level loops. We have two flavors: one where the loop count is predefined from an Integer variable and the other where a condition is used to determine its end.
Then we have a new type of variables, Dictionary, and three associated actions: build a dictionary with values, get an item from a dictionary and count the number of items in it. Each Dictionary item can be of a different type, and it is even possible to have items of type Dictionary. A Dictionary can be indexed by its key or by position, which is very useful to use inside loops.
It is now possible to start list and site workflows, but only SharePoint 2010 are supported. Workflows can be started synchronously, in which case, the originating workflow will wait for the result, or asynchronously, aka, fire and forget. Depending on the workflow selected, it may be necessary to specify values for its parameters.
Also new is the ability to assign tasks and start approval processes.
A perhaps not so used one is the capability to start a document translation process. The name is misleading, since it can also be used to translate list fields. The result translation is stored in another list.
Finally, we have the ability to call an HTTP web service. This will mostly used to call REST-style web services, but nothing prevents us from calling SOAP, since we can build a SOAP request using the string utility actions that the Designer offers. We can specify both request contents and headers, and retrieve the result, headers and HTTP status code. The problem is, SharePoint Designer workflows can only process results coming as JSON, not XML, but there are a number of translation web services that can be used to turn XML into JSON.
All in all, very useful additions!
SharePoint 2013 Designer workflows now has two new interesting options: the ability to call HTTP web services and the option to loop over some code a number of times. This, together with the new REST API, which supports querying lists and returning data in JSON, allows iterating through list items in a workflow, something that was not possible before.
In order to demonstrate this, let’s create a new Site Workflow in SharePoint Designer, that will iterate through the Tasks list:
Call it Process Tasks, for example, and make sure you select SharePoint 2013 as the platform type.
In the workflow designer, let’s start by creating a new stage, call it Retrieve Tasks:
In it, we add a new Set Workflow Variable action which creates a new String variable called url with the value “http://sp2013/_api/web/lists/getbytitle('Tasks')/items”. This uses the new REST API, and you can pass in additional options, such as for ordering by the DueDate field in descending order:
http://sp2013/_api/web/lists/getbytitle('Tasks')/items?$filter=DueDate gt DateTime’2014-07-31T00:00:00’
Next, we add a Dictionary variable (Build a Dictionary action), call it requestHeaders, and initialize it as this:
Both “Accept” and “Content-Type” entries are of the String type and they both contain the value “application/json;odata=verbose”, SharePoint REST API understands this and sets the response content type appropriately as JSON. If we don’t pass these values, the output would come as XML.
Following, add an Call an HTTP Web Service action and set its properties. The request will be the url variable:
Response content will go to a new variable called responseContent:
Response headers will go to a new variable called responseHeaders:
And the same goes for the response code (variable responseCode):
Then we set the request headers to be the requestHeaders variable we created just now, by clicking on the properties for the Call an HTTP Web Service action:
Now, create a new stage, call it Process Tasks, and, at the end of the initial stage, add a Go to Process Tasks action.
On the Process Tasks stage, add a Get an Item from a Dictionary action, set the item as d/results, the source variable reponseContent and the output to a new variable of type Dictionary called list. Then count items from this list variable using a Count Items in Dictionary action and store the result in a new Integer variable called count. This variable will tell us how many times we have to loop. Finally, create a new Integer variable called index and set it to 0 (Set Workflow Variable), this will be the loop index.
Next, add a loop (Loop n Times), call it Loop Task Items, and set the loop variable to count. Inside the loop, get value d/results([%Variable: index%]) using a Get an Item from a Dictionary action from responseContent and store it in a new Dictionary variable called item. Get some fields (Get an Item from a Dictionary) from the item variable, such as Title and DueDate (mind you, these will be task item fields) and store them in appropriate variables and do whatever you want with them, like logging its contents (Log). Time to increment the loop counter: add a Do Calculation action and in it increment the index variable into a new Integer variable called indexPlusOne. Then set the index variable to be the indexPlusOne (Set Workflow Variable). Finally, exit the loop and set the workflow status (Set Workflow Status action) to Finished. At the end of the stage, select Go to End of Workflow.
That’s it. Your workflow should look like this:
The new functionality makes SharePoint Designer workflows much more powerful than before. I will continue to talk about it in the following posts.
It’s official: now I’m a writer!
This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.
If you are still using XML mappings – .hbm.xml files –, there’s nothing wrong with that, but you may run into problems.
First, you will need to add these files as embedded resources in your project, if you are calling Configuration.AddAssembly(), Configuration.AddClass() or you are specifying the name of the assembly in the .config file like this:
These methods will look for .hbm.xml files as embedded resources in that assembly:
Alternatively, you can have the files on the filesystem, but you will have to call Configuration.AddDirectory(), Configuration.AddFile() or Configuration.AddInputStream(), passing the appropriate parameters.
In either case, the name of each .hbm.xml must end with .hbm.xml (of course!) and must be composed of the name of the associated class including its namespace.
If you don’t do this, NHibernate will not find your mappings, which will result in runtime errors.
This blog has moved to using Orchard. In the next few days, things may not be working exactly as they should; please bear with me, I will try my best to make the transition as smooth as possible.
In the meantime, the RSS for the posts is now https://weblogs.asp.net/ricardoperes/rss.
This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.