A typical use for Hash#merge is merging user supplied options with the default options for a particular action. Just now while doing this, I realized that the built-in merge method doesn’t merge nested hashes. First, let’s look at a trivial example use-case where you might need this.
ImageMagick Tips and Tricks
I’ve been using ImageMagick in one of my projects and I’ve had to do quite a bit of Googling. Below are some tips and tricks I’ve collected that might be useful to others.
Trim Whitespace From Your Image
$ convert -trim img.png
Create A New Image From Text
Note: You can combine this with the ‘trim’ tip above by passing the -trim argument.
$ convert -background white -fill black -pointsize 72 label:"Sean Fox" output.png
List Fonts ImageMagick Can Use
$ identify -list font
Building Ruby Gems Cheat Sheet
Here are some quick commands for building and installing ruby gems locally. This is just for reference; I’ve been meaning to make more of these kinds of posts.
Bump the Gem Version
To bump to version 1.0:
echo "1.0" > VERSION
Generate the Gemspec
rake gemspec
Build the Gem
gem build ./hello_world.gemspec
Install the Gem
gem install ./hello_world.gem
NHibernate AutoMapping Persister Error
If you’ve configured FluentNHibernate with automapping, it’s easy to run into a persister error like the one below.
NHibernate.MappingException: No persister for: XYZ.ProductName.Model.Customer
But this was working last time I compiled and I haven’t been writing database code. What could I have done?
The Problem
NHibernate cannot find your model. Did you move it? Maybe you were just doing some refactoring and you moved the models to a different namespace?
Check Your FluentConfiguration
First you should check your FluentConfiguration and make sure you’ve actually wired up the model that’s missing.
var automappingConfiguration = new MyAutomappingConfiguration();
Fluently.Configure()
.Database(SQLiteConfiguration.Standard.ConnectionString(connectionString).ShowSql())
.Mappings
(
m => m.AutoMappings.Add(AutoMap.AssemblyOf<Customer>(automappingConfiguration))
)
.BuildConfiguration();
Yep, there’s our Customer. So why can’t NHibernate find it?
Check Your AutomappingConfiguration
Next you should check your AutomappingConfiguration and make sure it’s pointing to the correct namespace.
public class MyAutomappingConfiguration : DefaultAutomappingConfiguration
{
public override bool ShouldMap(Type type)
{
return type.Namespace == "XYZ.ProductName.SomeOtherProject.Models";
}
}
Doh! I moved those models to a new namespace during some refactoring with Resharper. I better update the namespace in my AutomappingConfiguration.
—
Hopefully you’ve managed to help NHibernate find your models now.
Have fun coding!
Configuring FluentNHibernate with SQLite in .NET 4
Configuring FluentNHibernate with SQLite can be a bit painful, particularly because the SQLite assemblies are built separately for x86 and x64. On top of that, because NHibernate is loading the SQLite DLL at runtime, the DLL needs to be in a location that NHibernate can find it. When trying to set this up myself, I ran into the following error:
An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more details.
And the inner exception looked like this:
Could not create the driver from NHibernate.Driver.SQLite20Driver, NHibernate, Version=3.3.1.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4.
The Problem
Typically this error just means NHibernate cannot locate and load the SQLite DLL. This could be because you’re trying to load the 64-bit DLL under a 32-bit project or vice-versa. I noticed a lot of people were simply configuring their Visual Studio projects for x86 and referencing only the x86 SQLite DLL to solve this problem, but this is unnecessary. Below I’ll explain how to set this up properly.
The Solution
Basically the System.Data.SQLite DLL needs to be in the same directory as the NHibernate DLL. Typically, whichever Visual Studio project is set as the startup project (your main application interface) should have a reference to System.Data.SQLite. So just add the NuGet package to that project, as well as any test projects that may need access to the database as well.
The Long-winded Solution
Or if the above wasn’t clear enough…
Install FluentNHibernate
Firstly, you need to have FluentNHibernate installed and referenced in your project. For this, I would recommend installing NuGet.
After NuGet is installed, just grab the package using the GUI or run the Install-Package command from the NuGet prompt:
PM> Install-Package FluentNHibernate
You’ll reference FluentNHibernate from any project that uses it in the code, just like normal.
Configure FluentNHibernate
Make sure you’re building a valid NHibernate configuration in your code using Fluently.Configure() and that you’re using FluentNHibernate.Cfg.Db.SQLiteConfiguration.
Install SQLite
Using NuGet, grab the package using the GUI or run the Install-Package command from the NuGet prompt:
PM> Install-Package System.Data.SQLite
Make sure you’re installing System.Data.SQLite and NOT installing System.Data.SQLite.x86 or System.Data.SQLite.x64. The System.Data.SQLite package contains both the x86 and x64 versions of the DLL, which is what I would recommend if you want to compile your application for both 32-bit and 64-bit machines.
Reference SQLite
Add to reference to System.Data.SQLite to your primary application project (e.g. the startup project, the GUI, etc.). Also add a reference to any test projects that use the database, such as your NUnit tests.
You’re Done?
Does it work? If so, congrats! Happy coding!
It Didn’t Work
Ok, so if it didn’t work, you can try telling .NET which assembly to load.
Update Your App.config or Web.config
In your App.config or Web.config for your main application or any other projects that access the database, add the following:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<qualifyAssembly partialName="System.Data.SQLite"
fullName="System.Data.SQLite, Version=1.0.84.0,
Culture=neutral, PublicKeyToken=db937bc2d44ff139"/>
</assemblyBinding>
</runtime>
The qualifyAssembly element specifies the full name of the assembly that should be dynamically loaded when a partial name is used; this should ensure the correct version is loaded at runtime.
Also, if you’re wondering how I got the PublicKeyToken for the DLL, check out my article on finding the public key token for a .NET DLL or assembly.
Finish Line
You’re all done! Now you can use FluentNHibernate and SQLite in both x86 and x64 mode. The correct DLL should be loaded based on your project/compiler settings.
Happy hacking!
How to find the public key token for a .NET DLL or assembly
When using .NET, sometimes you need the public key token for a strongly named assembly. Below I’ll explain how to glean that information using sn or gacutil.
Where are these utilities?
The two utilities you can use to get public key tokens are sn and gacutil. You can find either of them in the Visual Studio Command Prompt or the .NET Framework directory.
Visual Studio Command Prompt
To get to the Visual Studio Command Prompt, just hit the Start menu and type Visual Studio Command Prompt into the finder. If you have Visual Studio installed, you should be able to find this tool.
.NET Framework Directory
Alternatively, you can also run these tools from the .NET Framework directory. For .NET 4.0 or 4.5, you’ll find the tools here: C:\Windows\Microsoft.NET\Framework\v4.0.30319
Just navigate to that directory in cmd.exe or PowerShell.
Public Key Tokens with sn
Just run sn -T followed by your DLL or assembly. Here’s an example:
PS > sn -T "C:\dev\project_name\packages\System.Data.SQLite.1.0.84.0\lib\net45\System.Data.SQLite.dll" Microsoft (R) .NET Framework Strong Name Utility Version 3.5.30729.1 Copyright (c) Microsoft Corporation. All rights reserved. Public key token is db937bc2d44ff139
Public Key Tokens with gacutil
If the DLL is in the GAC, you can do the same thing with gacutil:
PS > gacutil -l System.Data.SQLite Microsoft (R) .NET Global Assembly Cache Utility. Version 4.0.30319.1 Copyright (c) Microsoft Corporation. All rights reserved. The Global Assembly Cache contains the following assemblies: System.Data.SQLite, Version=1.0.84.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64 Number of items = 1
Now go get that token you were after!
Fixing .NET Framework 4 Client Profile Dependency Issues
If you’ve worked with .NET 4, you might have run into this before. You’re casually typing and clicking along and then you go to add a reference to your project; but suddenly your application won’t build any more. The error complains about your targeted framework and a Microsoft library dependency. This library is included in .NET, but it won’t add to my project! What gives?
The referenced assembly "StructureMap" could not be resolved because it has a dependency on "System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" which is not in the currently targeted framework ".NETFramework,Version=v4.0,Profile=Client". Please remove references to assemblies not in the targeted framework or consider retargeting your project.
The Problem
If you take a closer look at the error, you’ll notice the targeted framework includes the text Profile=Client.
The .NET Framework 4 Client Profile is a subset of the .NET Framework 4 that is optimized for client applications; it restricts the set of referenced assemblies to only those that are interesting to a client application. For example, it won’t make System.Web available by default because it is not typically valuable to client apps.
So if you started building a Forms app (or WCF or WPF), Visual Studio might have defaulted you to target the .NET Framework 4 Client Profile instead of just .NET Framework 4. And now, it’s complaining because you want to add libraries that a client application doesn’t typically have any use for.
The Solution
Right-click the project that needs the reference added, click properties, and update the project to target .NET Framework 4 instead of the Client Profile.
Now get back to work!
How To Fix DataGridView Rows Showing Up Without Data
The DataGridView is incredibly helpful for binding data sources to a grid, but sometimes working with it is a bit tricky. If you use the DataGridView control sparingly (or you’re just plain forgetful), you might run into an issue where you can see rows in the grid, but all the cells are empty!
The Problem
Not to worry! If you’re seeing the correct number of rows, you probably just have some visibility problems with the class being used.
In my case, I was trying to bind a list of proxies (List) like this:
private void BindProxyGrid(IList proxies)
{
var proxiesBindingList = new BindingList(proxies);
dgvProxies.DataSource = proxiesBindingList;
}
And my proxy class looked something like this:
public class Proxy
{
public string Ip;
public int Port;
}
The Solution
So why didn’t it work? Because the DataGridView requires properties and I was using public fields. Updating the class to use properties fixed the problem!
public class Proxy
{
public string Ip { get; set; }
public int Port { get; set; }
}
It works!
The Lesson Learned
If you’re using a BindingList with your DataGridView, you may need to adjust the visibility for any class members you want to display in the grid; for example, the DataGridView can’t access public fields or properties marked internal.
Happy coding!
Normalizing Line Endings Across Multiple Files
Recently I’ve been noticing some of my C# files have inconsistent line endings.
The Problem
The line endings in the following file are not consistent. Do you want to normalize the line endings?
This probably means some of the developers have been editing our source code using a text-editor (instead of Visual Studio) and they had their line endings set to “Unix” or “Mac” instead of “Dos/Windows”. This isn’t a big deal, though it is annoying.
Vim: Convert All Files to Dos/Windows Line Endings
Since I don’t know which files have this problem, I decided to just normalize all the line endings. There are various ways to do this, but I chose to use vim since the documentation on this topic is excellent.
To convert from any mixture of CRLF endings and LF-only endings, to CRLF endings:
:set ffs=dos :args **\*.cs :argdo w
We’re basically asking vim to assume Dos/Windows line endings, having it open all *.cs files (C# code files), then having it write the line-ending changes.
Downsides
This does change every single file that was found, regardless of the original line endings. It’s best to do this as one commit in source control to avoid any confusion.
Alternatives
You can also use unix2dos to do this conversion or any scripting language (python, perl, powershell).
Some people also let their source control handle their line endings. Git can enforce these line endings by updating them for you if you prefer. However, at my office, we choose not to let our source control alter our code in any way; we prefer to do that ourselves.
Now get back to coding!
Setting a Default Upstream Branch in Git
So you’re working in a branch in your Git repository, and you’ve just made some changes. You just ran git commit and now you want to merge any changes from upstream. So you issue a git pull and BAM!, you see this error:
# git pull You asked me to pull without telling me which branch you want to merge with, and 'branch.xyzbranch.merge' in your configuration file does not tell me, either. Please specify which branch you want to use on the command line and try again (e.g. 'git pull'). See git-pull(1) for details. If you often merge with the same branch, you may want to use something like the following in your configuration file: [branch "xyzbranch"] remote = merge = [remote " "] url = fetch = See git-config(1) for details.
So what gives? Why doesn’t git know what you’re trying to do?
Where is My Upstream Branch?
The problem is git has no idea which branch you want to pull from or push to. Chances are you made this branch like this:
# git branch xyzbranch
That creates a new branch in your git repository, but it’s not set up to track any remote (upstream) branches. You can use git remote show origin to see where your branches are pushing and pulling if you’d like to verify that.
# git remote show origin
* remote origin
Fetch URL: git@hostname:repository.git
Push URL: git@hostname:repository.git
HEAD branch: master
Remote branches:
another_branch tracked
master tracked
some_other_branch tracked
Local branches configured for 'git pull':
another_branch merges with remote another_branch
some_other_branch merges with remote some_other_branch
Local refs configured for 'git push':
another_branch pushes to another_branch (fast-forwardable)
master pushes to master (up to date)
some_other_branch pushes to some_other_branch (up to date)
So there is no upstream branch set for xyzbranch! That’s not really a problem, it just means you have to tell git where to pull changes from and where to push them to every time you use git pull and git push. But that’s annoying, so how do we fix it and set a default remote branch?
Setting Your Upstream Branch
If you’re on a branch called xyzbranch and you want to track the master branch, you could use git branch –set-upstream to do that like this:
# git fetch origin # git branch --set-upstream xyzbranch origin/master Branch xyzbranch set up to track remote branch master from origin.
And suddenly, voila!
# git pull Already up-to-date.
No more complaining from git!
For more tips and tricks on Git, check out GitReady.com.
Git it done!