Michael Hedgpeth
Michael Hedgpeth

Reputation: 7862

How to avoid duplication with QueryOver

I have two methods and don't like the duplication:

public Order LatestOrderOver(decimal amount)
{
    return session.QueryOver<Order>()
        .Where(o => o.Amount > amount)
        .OrderBy(sr => sr.CompleteUtcTime).Desc
        .Take(1)
        .SingleOrDefault<Order>();
}

public Order LatestAmericanOrderOver(decimal amount)
{
    return session.QueryOver<Order>()
        .Where(o => o.Amount > amount && o.Country == "USA")
        .OrderBy(sr => sr.CompleteUtcTime).Desc
        .Take(1)
        .SingleOrDefault<Order>();
}

What is the best way to avoid duplication when you have similar criteria (in the Where clause) used in the QueryOver and similar options at the end?

Upvotes: 1

Views: 173

Answers (2)

Miroslav Popovic
Miroslav Popovic

Reputation: 12128

Beside Guffa's suggestion, what do you think about an extension method?

public static class QueryOverExtensions
{
    public static Order LastOrder(this IQueryOver<Order, Order> query)
    {
        return query
            .Where(o => o.Amount > amount)
            .OrderBy(sr => sr.CompleteUtcTime).Desc
            .Take(1)
            .SingleOrDefault<Order>();
    }

    // Other query over extension methods
}

Then you could write your methods as:

public Order LatestOrderOver(decimal amount)
{
    return session.QueryOver<Order>()
       .LastOrder();
}

public Order LatestAmericanOrderOver()
{
    return session.QueryOver<Order>()
        .Where(o => o.Country == "USA")
        .LastOrder();
}

Upvotes: 0

Guffa
Guffa

Reputation: 700342

If you are using Linq To Objects, you can just refactor out the delegate:

private Order LatestOrderOver(Func<Order, bool> f) {
  return
    session.QueryOver<Order>()
    .Where(f)
    .OrderBy(sr => sr.CompleteUtcTime).Desc
    .Take(1)
    .SingleOrDefault<Order>();
}

public Order LatestOrderOver(decimal amount) {
  return LatestOrderOver(o => o.Amount > amount);
}

public Order LatestAmericanOrderOver(decimal amount) {
  return LatestOrderOver(o => o.Amount > amount && o.Country == "USA");
}

Otherwise it might work with just changing Func<> to Expression<>, but I don't have much experience with that.

Upvotes: 3

Related Questions