NHibernate - Eager Fetch and Pagination in one query

Print Content | More

Let’s consider these mappings:

<class name="Item" table="Item">
	<id name="Id" column="Id" type="int">
		<generator class="native" />
	</id>
	<property name="Name" column="Name" type="string" />
	<property name="Sort" column="Sort" type="int" />
	<bag name="Tags" inverse="true" lazy="true">
		<key column="ItemId" />
		<one-to-many class="Tag"/>
	</bag>
</class>

<class name="Tag" table="Tag">
	<id name="Id" column="Id" type="int">
		<generator class="native" />
	</id>
	<property name="Name" column="Name" type="string" not-null="true" />
	<many-to-one name="Item" column="ItemId" class="Item" not-null="true" />
</class>

 

Trying to paginate a query that uses eager fetching to retrieve the data in the ‘traditional’ way, that is using something similar to this piece of code:

ICriteria myCriteria = session.CreateCriteria<Item>("itm");
myCriteria.AddOrder(new Order("Sort", true))
	.SetFirstResult((pageIndex - 1)*pageSize)
	.SetMaxResults(pageSize)
	.SetResultTransformer(Transformers.DistinctRootEntity)
	.SetFetchMode("Tags", FetchMode.Eager);

 

Will simply FAIL, because eager fetching retrieves more data rows from the database due to the joins it performs, thus the ‘SetFirstResult()’ call will simply cut out some of your data.

One way to resolve the problem is to use a DetachedCriteria to actually get a projection of all the Ids of the items you want to paginate (applying any filtering and sorting you desire at this step) and later on use the projection to perform the real query that retrieves the data using eager fetching:

private static IList<Item> GetPagedData(int pageIndex, int pageSize)
{
	IList<Item> result;
	using (ISession session = NHelper.OpenSession())
	using (ITransaction tx = session.BeginTransaction())
	{
		// get the list of IDs corresponding to the page od data we wanna get
		DetachedCriteria detached = DetachedCriteria.For<Item>("itm2");
		detached.AddOrder(new Order("Sort", true))
			.SetFirstResult((pageIndex - 1)*pageSize)
			.SetMaxResults(pageSize)
			.SetProjection(Projections.Property("Id"));
		// get the real data
		ICriteria myCriteria = session.CreateCriteria<Item>("itm");

		myCriteria
			.Add(Subqueries.PropertyIn("Id", detached))
			.SetResultTransformer(Transformers.DistinctRootEntity)
			.SetFetchMode("Tags", FetchMode.Eager);
			
		result = myCriteria.List<Item>();

		tx.Commit();
	}
	return result;
}

 

If you look at the logs generated by NHibernate you will see that this code will result in a single query sent to your database engine, having called this function asking for page index 2 with a page size of 2 I obtain the following query:

SELECT this_.Id as Id1_1_, this_.Name as Name1_1_, this_.Sort as Sort1_1_, tags2_.ItemId as ItemId3_, tags2_.Id as Id3_, tags2_.Id as Id0_0_, tags2_.Name as Name0_0_, tags2_.ItemId as ItemId0_0_ FROM dbo.Item this_ left outer join dbo.Tag tags2_ on this_.Id=tags2_.ItemId WHERE this_.Id in (SELECT TOP 2 y0_ FROM (SELECT this_0_.Id as y0_, ROW_NUMBER() OVER(ORDER BY this_0_.Sort) as __hibernate_sort_row FROM dbo.Item this_0_) as query WHERE query.__hibernate_sort_row > 2 ORDER BY query.__hibernate_sort_row)

This technique helped me to reduce the number of queries made by the application a lot.



Eager, Nhibernate, Pagination

0 comments

Tomorrow’s DotNetMarche Workshop Live Streaming

Print Content | More

As anticipated in my previous post, if you cannot be there to attend the workshop directly (and you should be Open-mouthed smile), thanks to the guys at Ce.S.M.I. we will be able to offer you a live streaming of the event (crossing fingers for everything to work as expected...), here’s the link to attend the workshop online:

mms://mmedia.univpm.it/dotnetmarche.org

Since we are a ‘local’ User Group the workshop and the material will be presented in Italian; more info and the complete agenda on our official DotNetMarche website.

Thank you again for the support and opportunity you give us to share our passion for developing software even more.



Dotnetmarche, Workshop

0 comments

NHibernate - Eager Fetch, Order By and a strange behavior with ICriteria

Print Content | More

Working on Dexter I encountered a very strange NHibernate behavior (I’m using NHIbernate 2.1.2 GA and this is very close to be a bug in my opinion) while trying to apply the eager fetch mode to a child collection whose mapping contains an order-by attribute applied.

The scenario is this: you have 2 classes called: ‘Item’ and ‘Tag’, Item holds a collection of tags, the relation is mapped as inverse and we have an order-by clause applied to the collection mapping (the tags are ordered by name); we want to fetch a list of Item classes along with all its tags (to optimize things) and we want the result to be sorted by some field of the main Item class.

The problem is: performing the query using ICriteria and setting the eager fetch mode on the tags collection you don’t get the results with the order you expect (the one you specified in the ICriteria query).

To reproduce the behavior let’s consider the following mapping:


	
		
	
	
	
	
		
		
	



	
		
	
	
	


 

We can build-up a very simple to create some data in the database:

public void CreateTestData()
{
	string[] tagsName = new[] { "zapp", "crunch", "bang", "sbanf" };
	using (ISession session = NHelper.OpenSession())
	using (ITransaction tx = session.BeginTransaction())
	{
		// create some items
		for (int i = 0; i < 10; i++)
		{
			Item itm = new Item() { Name = "Item" + i, Sort = i };
			session.SaveOrUpdate(itm);
			
			Tag t = new Tag();
			t.Name = tagsName[i / 3];
			t.Item = itm;
			itm.Tags.Add(t);
			session.SaveOrUpdate(t);
		}
		tx.Commit();
	}
}

 

I can now write a very simple ICriteria to retrieve all the Items (alongside with their tags) ordering the result by the ‘Sort’ field; I expect to see 10 records in my result ordered from 0 to 10 in ascending order:

...
ICriteria myCriteria = session.CreateCriteria();

myCriteria
	.SetResultTransformer(Transformers.DistinctRootEntity)
	.SetFetchMode("Tags", FetchMode.Eager)
	.AddOrder(new Order("Sort", true));

result = myCriteria.List();
...

What I get instead are 10 records...but ordered by Tag name FIRST (which is the order I asked for in the mapping), I really expected this order by to be applied AFTER what I imposed while building the ICriteria.

To confirm the problem we can take a look at the query NHibernate generates and execute that in our SQL environment:

NHibernateEagerOrderBy1
As you can see this isn’t really what I expected, to double check I also tried to get the data using an HQL query:

IQuery query = session.CreateQuery("from Item itm left join fetch itm.Tags order by itm.Sort");

result = query.List();

But this time everything is fine...and I see the result ordered by ‘Sort’ first and after by tag’s Name:

NHibernateEagerOrderBy2

In the end: when using eager fetching with collection mapped with order-by clauses, always perform some tests to verify if what you obtain satisfies the order you imposed on your queries. If you get strange behaviors using ICriteria, try switching to HQL queries as they seems to act better according to you needs.

 

In the following solution you can find a test project to reproduce the problem:

 



Eager, Fetch, Hql, ICriteria, Nhibernate

0 comments

MSI: a simple Delete Files Custom Action

Print Content | More

Reviewing the Install/Uninstall process I’ve created using the standard Visual Studio Setup Project template, I’ve noticed that some files were always left on the installation folder after a complete program uninstall sequence.

The default behavior is to leave on the file system any file you didn’t explicitly added to the setup solution; so if you create temp files, configuration files or whatever you might need during the program execution, they will be left on the disk.

To get rid of them I’ve wrote this extremely simple custom action:

[RunInstaller(true)]
public partial class DeleteFilesCustomAction : Installer
{
	public DeleteFilesCustomAction()
	{
		InitializeComponent();
	}

	public override void Uninstall(IDictionary savedState)
	{
		base.Uninstall(savedState);
		try
		{
			// delete any addictional files (or comepletely remove the folder)
			string pathtodelete = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
			// MessageBox.Show("Deleting: " + pathtodelete);
			if (pathtodelete != null && Directory.Exists(pathtodelete))
			{
				// delete all the file inside this folder except SID.SetupSupport
				foreach (var file in Directory.GetFiles(pathtodelete))
				{
					// MessageBox.Show(file);
					if (!file.Contains(System.Reflection.Assembly.GetAssembly(typeof (DeleteFilesCustomAction)).GetName().Name))
						SafeDeleteFile(file);
				}
				foreach (var directory in Directory.GetDirectories(pathtodelete))
					SafeDeleteDirectory(directory);
			}
		}
		catch
		{
		}
	}

	private static void SafeDeleteFile(string file)
	{
		try
		{
			File.Delete(file);
		}
		catch
		{
		}
	}

	private static void SafeDeleteDirectory(string directory)
	{
		try
		{
			Directory.Delete(directory, true);
		}
		catch (Exception)
		{
		}
	}
}

You can use it just adding the custom action to an assembly you will also add to the setup project (right click, add...new project output...and point to the project that contains your custom actions); then in the Custom Actions Editor, add the specific action under the Uninstall section.



Custom Action, Uninstall, .net, Visual studio

0 comments

Passing a Delegate to an Attribute: a simple workaround

Print Content | More

Working on a very simple DataForm control for Winforms I had the need to pass a function delegate to an attribute that qualifies a property to generate a ComboBox on the UI. The function was mean to be used as a way to retrieve the set of values you use to populate the Items property of the ComboBox.

I quickly discovered that I cannot pass that delegate as a parameter using the standard attribute qualifying syntax because: an attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.

A quick and dirty workaround was to add a Dictionary<String, Func<IEnumerable>> to my DataForm control and a function to actually ‘register’ the delegate you want to use to populate the combox. The delegate is registered using a string key that you will later on pass to the attribute that qualifies the property.

Here are some code snippets taken from the DataForm:

...
private readonly Dictionary<string, Func<IEnumerable>> _loadItemsFunctions = new Dictionary<string, Func<IEnumerable>>();

/// <summary>
/// Registers the load item function, if a function exists with the same key
/// it gets overwritten.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="deleg">The deleg.</param>
public void RegisterLoadItemFunc(string key, Func<IEnumerable> deleg)
{
	_loadItemsFunctions[key] = deleg;
}
...

and the attribute class:

[AttributeUsage(AttributeTargets.Property)]
public class UiHintComboBoxAttribute : Attribute
{
	public UiHintComboBoxAttribute()
	{
		DropDownStyle = ComboBoxStyle.DropDownList;
		BindType = BindTo.SelectedValue;
	}

	/// <summary>
	/// Gets or sets the load items function, it's a string placeholder for a 
	/// function registered in the instance of the control that will use it.
	/// </summary>
	/// <value>The load items func.</value>
	public string LoadItemsFunc { get; set; }

	public string DisplayMember { get; set; }

	public string ValueMember { get; set; }

	public ComboBoxStyle DropDownStyle { get; set; }

	public BindTo BindType { get; set; }

	public enum BindTo
	{
		SelectedValue,
		SelectedItem
	}
}

A similar technique can be used if you need to pass descriptive strings along with your attributes and you need to localize those strings: you pass in a reference to a dictionary you populate with phrases in the correct language.



.net, Delegate, Attribute

0 comments

Are you ready for the upcoming DotNetMarche workshop on July 16 ?

Print Content | More

This announce will be particularly interesting for the people that live and work Italy: our .Net User Group DotNetMarche organizes another cross community Workshop.

This time we team up with DotDotNet, Gaia srl and Ce.S.M.I. of the University of Ancona (Italy) to offer you a complete overview over the challenges you have to face when designing and building up a Silverlight SOA application: from the relationships with the customers, the design and the UI/UX prototyping, the application lifecycle and the coding stage using various patterns...I know it’s quite an ambitious plan!

For the registration, the complete agenda and the details on the location and speakers take a look at our website: http://dotnetmarche.org

This time, thanks to the guys at Ce.S.M.I, we will also probably be able to offer you the whole workshop using internet streaming too, so if you cannot be physically there you have a chance to follow us anyway! For further details on how to attend the workshop online keep following this blog or our official DotNetMarche website.

See you there!



Dotnetmarche, Workshop, Silverlight

0 comments

Silverlight / WPF: is it possible to bind to an explicit interface indexer implementation?

Print Content | More

The WPF binding system allows you to bind to Indexers and properties and it also have a nice feature that allows you to bind to the explicit implementation of interfaces’ members, allowing you to resolve possible ambiguities if the properties have the same names, let’s consider this simple example you have the following two interfaces and a class that implements them:

public interface IFirst
{
   string this[string index] { get; }

   String Name { get; }
}

public interface ISecond
{
   string this[string index] { get; }

   String Name { get; }
}

public class Entity : IFirst, ISecond
{
   public string Name
   {
       get { return "Class Name"; }
   }
   
   public string this[string index]
   {
       get { return "Class Indexer"; }
   }

   string IFirst.this[string index]
   {
       get { return "First Indexer"; }
   }

   string IFirst.Name
   {
       get { return "First Name"; }
   }

   string ISecond.this[string index]
   {
       get { return "Second Indexer"; }
   }

   string ISecond.Name
   {
       get { return "Second Name"; }
   }
}

And you can bind them with a syntax like this:


   
   
   

   
   
   
   
   
   
   

If you run this code you will see the correct binding working for the first 4 textboxes:

IndexersBinding

I wasn’t able to find any binding syntax to have the explicitly implemented indexers binding work as expected, so I have to conclude that, as far as I know, this particular binding type is not yet supported (or this is a bug in the WPF binding system). If you have more info on the subject please, let me know.

Silverlight currently does not support binding to explicit interface implementations: when you try to write something similar to that the Xaml parser give you the E_UNEXPECTED error. I think this is one of the reasons why the Silverlight Team introduced a new interface for validation and error reporting like INotifyDataErrorInfo instead of just relying on the IDataErrorInfo typical to WPF: the IDataErrorInfo indexer (used to access the error’s collection) most of the time it’s implemented using explicit interface implementation; I would really like to see a porting of that interface in WPF soon cause I think it has a better design than the current IDataErrorInfo.

What you can do then? Well...nothing much about the explicit interface binding in Silverlight, it’s not supported...and you can’t write any binding extension to add it, so we just have to leave without it; you can maybe write a binding extension to fix the indexers’ binding, but that will not be applicable to Silverlight projects.

A small workaround I use is to define an interface - called IIndexable - that simply define an indexer and write an implementation class that act as a wrapper around the explicit indexer implementation I want to bind too...not much elegant, but it works in both worlds and you can restrict the access to the indexers implementing the get and set operations as needed:

public interface IIndexable
{
   TResult this[TKey index] { get; }
}

public class IndexableWrapper : IIndexable
{
   public IndexableWrapper(IFirst wrapped)
   {
       _class = wrapped;
   }

   private readonly IFirst _class;

   public string this[string index]
   {
       get { return _class[index]; }
   }
}

// in your entity class you can now add a member you can freely bind to
...
public IIndexable FirstIndexer
{
  get { return  (new IndexableWrapper(this)); }
}

You can check the solution containing the full samples just downloading this file, it contains both the WPF and the Silverlight solutions:



Binding, Indexer, Interface, Silverlight, WPF

2 comments

Exams 071-518 and 071-519 passed successfully

Print Content | More

I’ll make this short post to test the new Windows Live Writer (which seems quite cool at a first look).

Yesterday I got some good news, I passed both the certification exams I tried some time ago:

  • 071-518 - Pro: Design & Develop Windows Apps Using MS .NET Framework 4
  • 071-519 - Pro: Designing & Developing Web Apps Using MS .NET Framework 4

Maybe I’ll try some more of them now :).



Certification, Exam

1 comments

Winforms: improving rendering performances with BackgroundImage and BackgroundImageLayout

Print Content | More

Even after years you always have something to learn...this time I had a windows forms application with a lot of graphics in it: big and heavy background images, graphic buttons with transparent background, mixed bitmaps, Jpegs and PNGs...the whole thing rendering performance was just...horrible! The form was rending slowly piece by piece (with a lot of artifacts) giving the user a very poor feeling.

To improve the rendering speed you can use some standard techniques, here are a couple of them:

  • Calling BeginUpdate() before populating data intensive controls (ComboBox, ListBox DataGrid, etc...) and EndUpdate() when done.
  • Calling SuspendLayout() and ResumeLayout() on parent controls and forms to optimize layout changes. Bounds, Size, Location, Visible, and Text for AutoSize controls causes the layout changes. You should call these methods when performing multiple layout changes and always on parent control of the controls that you are changing layout for.

However the biggest impact was given when I changed the following properties:

  • Avoid using BackColor=Transparent when it’s not strictly needed, windows forms transparency is done with a two pass rendering, so prefer solid colors whenever possible.
  • If you use BackgroundImage heavily and with very large images do not underestimate the impact of changing the BackgroundImageLayout property too: the default value it’s ‘Tile’ which means that the rendering engine will do additional computations to figure out if it have to replicate it horizontally and vertically and this is a big show stopper when dealing with performances! Change it to ‘none’ or to the value most appropriate for you (to be honest ‘none’ should be the default value here).
  • Set the DoubleBuffered property to true (you need to use reflection if you want to set this on dynamically created controls because it’s a protected method) or use:
    SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); in your control’s constructor.

My recommendation is to change the BackgroundImageLayout from the default ‘Tile’ value to something else (if you don’t really need the tile behavior) for all the controls that use a Background Image, the speed-up in rendering was surprising.

If you use PictureBoxes too, check the ‘SizeMode’ and set it to an appropriate value in order to reduce unnecessary scaling of the images.



    Windows forms, Rendering, Performance

    0 comments

    Microsoft Expression Encoder - using LiveJob, LiveDeviceSource and PreviewWindow

    Print Content | More

    For the proof of concept about a recording and encoding application I’m building, I had the need to show the preview of the actual data stream I can grab from a video source before the actual encoding job started. In the previous example you could view the result of the encoding operation and if you used that code, you could saw a delay between your actions in front of the webcam and the preview of the encoded stream.

    To solve the issue a little more dig into Expression Encoder was needed, at the point of this writing the documentation won’t help you too much cause it’s quite poor compared to the information we’re used to have from MSDN.

    So let’s introduce again our main actors:

    • LiveJob - this is the main class you use to perform the encoding from different sources, it has the ability to enumerate the devices, activate the selected sources, chose between preset encoding profiles or use your custom ones, do the dirty encoding job and show a preview of the encoded stream.
    • LiveDeviceSource - this class represent your actual source (or sources - it can mix video and audio) for the raw bits you will pass to the encoder, you can use this to gain access to the selected devices and use their configuration dialog; you can also specify a preview window to be used to see the uncompressed stream.
    • PreviewWindow - this is a wrapper around a plain old winform control or around a WPF window (something with an handle in short, see my previous post).

    To fulfill our requirement we can modify the previous Encoding service in the following way:

    • Add two properties for the PreviewWindows: one for the raw stream preview coming from the webcam (we call this LivePreviewWindow) and one for the encoded stream (we call it EncodedPreviewWindow)
    • Add a private variable to store the LiveDeviceSource we get from mixing the selected devices.
    • To display the raw preview, during the device activation we need to set the PreviewWindow property of the active LiveDeviceSource and then we need to call the ActivateSource() function on the LiveJob class (this will be done in the ActivateDevices() function) passing the newly created LiveDeviceSource as parameter; this will activate the preview.
    • To display the encoded preview, we need to set the OutputPreviewWindow of the LiveJob class before calling the StartEncoding() function (you can see it in the StartCapture() function).

    If you leave those properties empty the preview will be disabled; here’s the new code for the class:

    public class EncodingService : IDisposable
    {
    /// <summary>
    /// job used to perform the real encoding and mixing of video and audio sources
    /// </summary>
    readonly LiveJob _encodeJob = new LiveJob();
    
    /// <summary>
    /// the active device source to show the preview and perform the encoding job
    /// </summary>
    private LiveDeviceSource _activeSource;
    
    /// <summary>
    /// enumerating the devices is a breeze, the LiveJob class does it for you.
    /// </summary>
    public ReadOnlyCollection<LiveDevice> VideoDevices { get { return _encodeJob.VideoDevices; } }
    
    /// <summary>
    /// enumerating the devices is a breeze, the LiveJob class does it for you.
    /// </summary>
    public ReadOnlyCollection<LiveDevice> AudioDevices { get { return _encodeJob.AudioDevices; } }
    
    /// <summary>
    /// preview window used to show the live stream (not the encoded one)
    /// </summary>
    public PreviewWindow LivePreviewWindow { get; set; }
    
    /// <summary>
    /// preview window used to show the encoded stream
    /// </summary>
    public PreviewWindow EncodedPreviewWindow { get; set; }
    
    public void ActivateDevices(LiveDevice video, LiveDevice audio)
    {
        DeactivateDevices();
        // first off: add a device source specifying the video and audio device you'll be using
        _activeSource = _encodeJob.AddDeviceSource(video, audio);
        // specify a preview window (something with a Handle - any winform control or a WPF window)
        if (_activeSource.PreviewWindow == null && LivePreviewWindow != null)
            _activeSource.PreviewWindow = LivePreviewWindow;
        // activate the source
        _encodeJob.ActivateSource(_activeSource);
    }
    
    public void DeactivateDevices()
    {
        if (_activeSource != null && _activeSource.IsActive)
            _encodeJob.RemoveDeviceSource(_activeSource);
    }
    
    public void StartCapture(LiveDevice video, LiveDevice audio, string outputFile)
    {
        // assign an output filename
        if (!string.IsNullOrEmpty(outputFile))
            _encodeJob.OutputFileName = outputFile;
        else
            _encodeJob.OutputFormat = new WindowsMediaBroadcastOutputFormat();
        // specify a preview window (something with a Handle - any winform control or a WPF window)
        if (_encodeJob.OutputPreviewWindow == null && EncodedPreviewWindow != null)
            _encodeJob.OutputPreviewWindow = EncodedPreviewWindow;
        // start the job (this activates the preview too)
        _encodeJob.StartEncoding();
    }
    
    public void StopCapture()
    {
        _encodeJob.StopEncoding();
    }
    
    public void Dispose()
    {
        SafeDispose(_encodeJob);
    }
    
    private static void SafeDispose(LiveJob job)
    {
        try
        {
            if (job != null)
            {
                job.StopEncoding();
                job.Dispose();
            }
        }
        catch (Exception ex)
        {
            // sometimes I get a COM exception when disposing the job...it needs further investigation
            System.Diagnostics.Debug.WriteLine(ex);
        }
    }
    
    /// <summary>
    /// states if you can activate the devices
    /// </summary>
    public bool CanActivate
    {
        get { return _activeSource == null || !_activeSource.IsActive; }
    }
    
    /// <summary>
    /// states if we are streaming something to the preview window
    /// </summary>
    public bool IsActive
    {
        get { return _activeSource != null && _activeSource.IsActive; }
    }
    
    /// <summary>
    /// states if you can start the encoding job
    /// </summary>
    public bool CanCapture
    {
        get { return IsActive && !_encodeJob.IsCapturing; }
    }
    
    /// <summary>
    /// states if we are performing the actual encoding job
    /// </summary>
    public bool IsCapturing
    {
        get { return _encodeJob.IsCapturing; }
    }
    }

    To use this service class you must first call ActivateDevices() to create the live source and activate it, then you can start and stop the encoding job using the StartEncoding() and StopEncoding functions.

    As a side note: pay very good attention to the size of the PreviewWindow: if you are building a WPF application and you use a WindowsFormsHost and a Panel controls to display the previews...the sizes of those controls will likely be (0,0) at the moment of creation due to the WPF rendering pipeline (I did this mistake too), so you will probably need to call PreviewWindow.SetSize() or delay the creation of those controls until you know the dimensions of the preview rendering boxes.

    In the quick and dirty demo application I built, I ended up having an ugly fix for this issue:

    private void PreviewRect_SizeChanged(object sender, SizeChangedEventArgs e)
    {
      _vm.LivePreviewWindow.SetSize(new Size((int)PreviewRect.RenderSize.Width, (int)PreviewRect.RenderSize.Height));
    }

    Next time I’ll show you a trick on how to add some overlays over the WindowsFormsHost controls to add some cool UI effects to your previews.



    Expression, Encoder, Wpf, PreviewWindow

    0 comments