Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FluentNHibernate filter with parameterized IN clause

In Fluent NHibernate, is it possible to add a parameter to a filter of type List<int> so that the filter condition generates a WHERE SomeColumn IN (@x, @y, @z) ?

My use case is to fetch an invoice and a subset of its lines, given the ID of the invoice and a list of invoice line numbers. I want to eager fetch the lines in the same roundtrip as the invoice. I assume it is done something like this, but I cannot find the correct type declaration for the parameter type:

Domain objects:

public class Invoice {
  public int Id {get;set;}
  public List<InvoiceLine> Lines {get;set;}
}

public class InvoiceLine {
  public int Id {get;set}
  public int LineNumber {get;set;}
}

Mappings:

public class InvoiceMap : ClassMap<Invoice> {
  public InvoiceMap() {
    Id(x => x.Id);
    HasMany(x => x.Lines).ApplyFilter<OnlyLinesWithNumbersFilter>();
  }
}

public class InvoiceLineMap : ClassMap<InvoiceLine> {
  public InvoiceLineMap() {
    Id(x => x.Id);
    Map(x => x.LineNumber);
  }
}

Filter definition:

public class OnlyLinesWithNumbersFilter : FilterDefinition
{
    public OnlyLinesWithNumbersFilter()
    {
        WithName("OnlyLinesWithNumbers");
        WithCondition("LineNumber IN (:LineNumbers)");
        AddParameter("LineNumbers",?? What to put here ??);
    }
}

Query:

var filterName = "OnlyLinesWithNumbers";
session.EnableFilter(filterName).SetParameterList("LineNumbers", new[] {1,2,3});

var query = session.QueryOver<Invoice>()
       .Where(i => i.Id == 42)
       .Fetch(i => i.Lines).Eager
       .TransformUsing(new DistinctRootEntityResultTransformer());

var result = query.SingleOrDefault();
session.DisableFilter(filterName);
like image 490
Jonas Høgh Avatar asked Jul 14 '11 07:07

Jonas Høgh


2 Answers

you can write

var list = session.QueryOver<Invoice>()  
                  .WhereRestrictionOn(p => p.SomeColumn)  
                  .IsIn(someList)  
                  .List();  
like image 62
VahidN Avatar answered Nov 14 '22 03:11

VahidN


To use NHibernate Filters with arrays, put NHibernateUtil.Int32 in AddParameter method, so do like this:

public class OnlyLinesWithNumbersFilter : FilterDefinition
{
    public OnlyLinesWithNumbersFilter()
    {
        WithName("OnlyLinesWithNumbers");
        WithCondition("LineNumber IN (:LineNumbers)");
        AddParameter("LineNumbers", NHibernateUtil.Int32);
    }
}

And when you enabled filter, set an array in SetParameterList

int[] lines = new int[] {1, 2, 3};
session.EnableFilter("OnlyLinesWithNumbers").SetParameterList("LineNumbers", lines);

In my tests I use NHibernate 4.0.0.400

like image 38
Juliano Oliveira Avatar answered Nov 14 '22 01:11

Juliano Oliveira