NHibernate.Criterion Extensions workaround
I've been working with Fluent NHibernate for the past month or so, and I realized while writing an NHibernate query that the NHibernate Criterion's Restrictions class isn't very refactor-friendly. The refactorability of Fluent NHibernate is ultimately why we've decided to use it. It does take a little longer to set up than some other ORMs, but in the long-run it's nice to be able to change a property name and refactor.
... except the property names are hard-coded in the Criteria!
My workaround for this is to use a bit of static reflection a-la-FNH, and maintain code that is easily refactored.
For instance, I've created a static utility class (Showing the Restrictions.Eq() substitute):
public static class CriterionExtensions
{
public static SimpleExpression Eq<T>(
Expression<Func<T, object>> exp, object value
)
{
var memberExpression = GetMemberExpression(exp);
string propertyName = ((PropertyInfo)memberExpression.Member).Name;
if (!string.IsNullOrEmpty(propertyName))
return Restrictions.Eq(propertyName, value);
else
return null;
}
private static MemberExpression GetMemberExpression<T>(
Expression<Func<T, object>> expression
)
{
MemberExpression memberExpression = null;
if (expression.Body.NodeType == ExpressionType.Convert)
{
var body = (UnaryExpression)expression.Body;
memberExpression = body.Operand as MemberExpression;
}
else if (expression.Body.NodeType == ExpressionType.MemberAccess)
{
memberExpression = expression.Body as MemberExpression;
}
if (memberExpression == null)
{
throw new ArgumentException("Not a member access", "member");
}
return memberExpression;
}
}
And to use this code, you can create an aliased using directive and call it in code:
using Ensure = MyNamespace.Extensions.Criterion.CriterionExtensions;
/* class declarations and whatnot */
internal IEnumerable<Product> GetAll(int shelfNumber)
{
var session = SessionManager.GetCurrentSession();
return session.CreateCriteria<Product>()
.Add(Ensure.Eq<Product>(x => x.ShelfNumber, shelfNumber))
.List<Product>();
}
It's pretty simple to use and is easily refactored. You may be able to add your *extensions* to a namespace: NHibernate.Criterion and call your class Restrictions, but I didn't try this (I don't like mixing namespaces). Let me know what you think!
CopyCat Rails’ Time Extensions
I've become a fan of Ruby's simple syntax. My favorite thing is the ActiveSupport's Numeric Time Extensions. I'm starting a library of useful extensions, and I'm going to be adding a number of shortcuts to mock these extensions.
For those of you that don't want to follow the link, check out the syntax:
# equivalent to Time.now.advance(:months => 1) 1.month.from_now # equivalent to Time.now.advance(:years => 2) 2.years.from_now # equivalent to Time.now.advance(:months => 4, :years => 5) (4.months + 5.years).from_now
Here is what I've gotten so far (it only includes int for now):
public static class DateExtensionsThatMockRuby
{
/// <summary>
/// Retrieve the number of ticks for x Days.
/// <example>long ticks = 5.Days();</example>
/// </summary>
/// <param name="i"></param>
/// <returns>ticks</returns>
public static long Days(this int i)
{
return new TimeSpan(i, 0, 0, 0).Ticks;
}
/// <summary>
/// Retrieve the number of ticks for x Hours.
/// </summary>
/// <example>long ticks = 15.Hours();</example>
/// <param name="i"></param>
/// <returns>ticks</returns>
public static long Hours(this int i)
{
return new TimeSpan(0, i, 0, 0).Ticks;
}
/// <summary>
/// Retrieve the number of ticks for x Minutes
/// </summary>
/// <example>long ticks = 97.Minutes();</example>
/// <param name="i"></param>
/// <returns>ticks</returns>
public static long Minutes(this int i)
{
return new TimeSpan(0, i, 0).Ticks;
}
/// <summary>
/// Retrieve the number of ticks for x Seconds
/// </summary>
/// <example>long ticks = 3000.Seconds();</example>
/// <param name="i"></param>
/// <returns>ticks</returns>
public static long Seconds(this int i)
{
return new TimeSpan(0, 0, i).Ticks;
}
/// <summary>
/// Retrieve the number of ticks for x Milliseconds
/// </summary>
/// <example>long ticks = 3000.Milliseconds();</example>
/// <param name="i"></param>
/// <returns>ticks</returns>
public static long Milliseconds(this int i)
{
return new TimeSpan(0, 0, 0, 0, i).Ticks;
}
/// <summary>
/// Retrieve a DateTime object from ticks
/// <example>DateTime dt = 236423690923466.AsDateTime();</example>
/// /// <example>DateTime dt = 10.Days().AsDateTime();</example>
/// </summary>
/// <param name="ticks"></param>
/// <returns>DateTime</returns>
public static DateTime AsDateTime(this long ticks)
{
return new DateTime(ticks);
}
/// <summary>
/// Retrieve a DateTime object from ticks
/// <example>DateTime dt = 236423690923466.AsDateTime(DateTimeKind.Utc);</example>
/// /// <example>DateTime dt = 10.Days().AsDateTime(DateTimeKind.Utc);</example>
/// </summary>
/// <param name="ticks"></param>
/// <returns>DateTime</returns>
public static DateTime AsDateTime(this long ticks, DateTimeKind kind)
{
return new DateTime(ticks, kind);
}
}
DRY! GenericComparer for sorting Generic Lists
I'm a pretty firm believer in the Ruby/Ruby on Rails idea of DRY ("Don't Repeat Yourself").
That said, I get pretty tired of writing comparers for sorting lists and generic lists. Every one of these comparers is exactly the same: you specify a list of properties related to the object and a sort direction, then call compare on those properties.
This can be changed with a little reflection:
public class GenericComparer<T> : IComparer<T>
{
public string SortExpression { get; set; }
public int SortDirection { get; set; } // 0:Ascending, 1:Descending
public GenericComparer(string sortExpression, int sortDirection)
{
this.SortExpression = sortExpression;
this.SortDirection = sortDirection;
}
public GenericComparer() { }
#region IComparer<T> Members
public int Compare(T x, T y)
{
PropertyInfo propertyInfo = typeof(T).GetProperty(SortExpression);
IComparable obj1 = (IComparable)propertyInfo.GetValue(x, null);
IComparable obj2 = (IComparable)propertyInfo.GetValue(y, null);
if (SortDirection == 0)
{
return obj1.CompareTo(obj2);
}
else return obj2.CompareTo(obj1);
}
#endregion
}
This is a code snippet I love to have in my arsenal.
Here's how you use it:
List<MyObject> objectList = GetObjects(); /* from your repository or whatever */
objectList.Sort(new GenericComparer<MyObject>("ObjectPropertyName", (int)SortDirection.Descending));
dropdown.DataSource = objectList;
dropdown.DataBind();
Note that Sort returns void. This means you can't throw this to the right of a DataSource call. You'd have to call this, then call your DataSource/DataBind.
Quickly create a Dictionary using Linq to Objects
When working with collections or lists, sometimes you just need to get a simple dictionary.
There are a number of ways to do this, but the ToDictionary method seems promising.
For isntance:
IList<Person> people = new List<Person>();
people.Add(new Person
{
FirstName = "Jim",
LastName="Schubert",
Age=29,
Phone="123-333-4444"
});
people.Add(new Person
{
FirstName = "Joe",
LastName="Schubert",
Age=25,
Phone="800-999-1111"
});
Dictionary<int,string> names = people.ToDictionary(k => k.Age, v => v.FirstName);
There may not be many uses for this type of syntax, but simple transformations like this make Linq fun.
Displaying multiple fields in a Dropdownlist’s DataTextField
I've encountered this problem on occasion, where I want to display more than one field in a dropdownlist's DataTextField property. In the past, I've overcome this problem by rewriting a SQL statement, or adding another column in the database itself to accomodate my needs.
In one of my classes (INFO 465: Projects in Information Systems @ VCU), we're working from a database which we're not allowed to change. The reason we can't change it is because the instructor uses the same database for his examples. I could just write another method into my business logic layer, but it would get cluttered pretty quickly.
So, I decided to make use of LINQ and found the following solution:
ddlUsers.DataSource = BLL.Employee.GetEmployees()
.Select(be =>
new {
ID = be.Id,
FullName = String.Format("{0}{1}{2}",
be.LastName,
(!string.IsNullOrEmpty(be.FirstName) ? ", " : string.Empty),
be.FirstName)
}).AsEnumerable();
This takes the List of Business Entity objects and uses the LINQ select statement to generate an implicit/anonymous object from that. The only downfall to this method is that the new object only has local scope. But, since I'm only using this in a dropdown, it's a pretty nifty trick.
T-SQL Multi-Table Delete
I was trying to run a DELETE query on multiple tables and I kept getting this error:
The DELETE statement conflicted with the REFERENCE constraint
I'm not that great with SQL, but I can get by. DELETEs have always been somethng that have given me trouble. So, I thought I'd share this simple fix.
DELETE FROM PRODUCT FROM BOOK WHERE BOOK.ID = PRODUCT.BOOK_ID AND BOOK.ID = @BOOK_ID
You just have to make sure you put the table with the FK as the first table in the query.
I guess I should have paid a little more attention in Database class. We learned Oracle, which is different from Microsoft's SQL in many ways.
