Right, after a lot more experimentation I've come to the conclusion that
it's to do with generic type parameters. I've basically extracted the logic
out of your GenericRepository, reducing it until I can replicate the issue
in the smallest possible form. Take the following test:
    <Test()> _
    Public Sub TestLinq()
        Dim flRepos As New Repository(_source)

        flRepos.Save(New Product())
        flRepos.Save(New Product())

        flRepos.Query(Function(x As Product) (x.Id = 2))
        GetById(Of Product)(2, flRepos)
    End Sub

    Public Function GetById(Of T As IHasIntId)(ByVal Id As Integer, ByVal
flRepos As IRepository) As T()
        Return flRepos.Query(Function(x As T) (x.Id = 2))
    End Function

There's a direct Query call on the repository, then there's a call to the
same method inside a helper method that uses a generic type. The direct
Query call succeeds, but the GetById call fails.

If you change the helper method to this:

    Public Function GetById(Of T As IHasIntId)(ByVal Id As Integer, ByVal
flRepos As IRepository) As Product()
        Return flRepos.Query(Function(x As Product) (x.Id = 2))
    End Function

Then it suddenly works. Notice the T is not actually used and it's hard
coded to Product.

My main conclusion is that this is definitely not a Fluent NHibernate issue.
It's something wrong with how Linq to NHibernate handles VBs generic
parameters.

A workaround, and it's not a nice one, is to either have a repository per
type, or create your generic repository in C# (I tried this and it works
without any trouble).

On Thu, Jan 8, 2009 at 10:42 AM, James Gregory <jagregory....@gmail.com>wrote:

> I'll take a look at your GenericRepository, see if I can replicate the
> issue.
>
>
> On Thu, Jan 8, 2009 at 4:52 AM, Josh Pollard <j...@glmotorsports.net>wrote:
>
>>
>> well now i feel dumb and bad. first off, i wasnt able to get your
>> example to compile, but it was probably more due to my lack of
>> knowledge around sqlite than anything. so i decided to write another
>> unit test of my own that basically looks like this:
>>
>>
>>        Dim flRepos As New Repository(session)
>>         Dim id As Integer = 1
>>         Dim product = flRepos.Query(Of Product)(Function(p As Product)
>> p.Id = id).FirstOrDefault()
>>
>>        Assert.AreEqual(id, product.Id)
>>
>> and it passed. so the problem doesnt look like its in fluent
>> nhibernate from that stand point. But if you look up at my original
>> question, you'll see that I'm trying to wrap the fluent nhibernate
>> repository in my own generic repository. When I then call the GetById
>> method, which I believe does the same thing as what I have in the code
>> in this message, I get an exception trying to cast Int to Product.
>>
>> Does that make sense?
>>
>>
>> On Jan 7, 5:42 pm, "James Gregory" <jagregory....@gmail.com> wrote:
>> > Josh: I've tried reproducing your problem, but I haven't been able to. I
>> > created a Product class, a ProductMap, and then wrote a little unit test
>> to
>> > see if it worked, and it did.
>> > <TestFixture()> _
>> > Public Class VbLinqTests
>> >     Private _source As ISessionSource
>> >
>> >     <SetUp()> _
>> >     Public Sub CreateDatabase()
>> >         Dim properties As IDictionary(Of String, String) = New
>> > SQLiteConfiguration() _
>> >             .UseOuterJoin() _
>> >             .InMemory() _
>> >             .ToProperties()
>> >
>> >         _source = New
>> > SingleConnectionSessionSourceForSQLiteInMemoryTesting(properties, New
>> > TestModel())
>> >         _source.BuildSchema()
>> >     End Sub
>> >
>> >     <Test()> _
>> >     Public Sub TestLinq()
>> >         Dim flRepos As New Repository(_source)
>> >
>> >         flRepos.Save(New Product())
>> >         flRepos.Save(New Product())
>> >         flRepos.Save(New Product())
>> >         flRepos.Save(New Product())
>> >
>> >         Dim product As Product = flRepos.Query(Of Product)(Function(p As
>> > Product) p.Id > 1).ToList().FirstOrDefault
>> >
>> >         Assert.NotNull(product)
>> >     End Sub
>> > End Class
>> >
>> > Can you try running that yourself to see what happens?
>> >
>> > On Tue, Jan 6, 2009 at 11:00 PM, Josh Pollard <j...@glmotorsports.net
>> >wrote:
>> >
>> >
>> >
>> > > I did some more investigating and it looks like Linq2NHib only pukes
>> > > when using lambda expressions in VB. The following works:
>> >
>> > > Dim product = (From p In session.Linq(Of Product)() _
>> > >                        Where p.Id = testId _
>> > >                        Select p).FirstOrDefault()
>> >
>> > > Obviously that isn't using Fluent NHib at all. So the question is, how
>> > > do I use Fluent NHib without using lambdas? I think the problem is
>> > > that I don't know what us as my "in"
>> >
>> > > Any ideas on how to cram a full linq query into the Fluent NHib Query
>> > > method?
>> >
>> > > On Jan 5, 3:31 pm, "Jeremy Skinner" <jer...@jeremyskinner.co.uk>
>> > > wrote:
>> > > > I can't be certain as I haven't got VB installed to test this, but
>> it
>> > > > certainly appears to be the case. Linq to NHibernate's unit tests
>> are all
>> > > in
>> > > > C# so it doesn't surprise me that the differences in VB's expression
>> > > trees
>> > > > have been missed.
>> >
>> > > > 2009/1/5 RalyDSM <j...@glmotorsports.net>
>> >
>> > > > > so I guess i need to take this problem to the linq-to-nhibernate
>> > > > > guys...
>> >
>> > > > > On Jan 5, 3:19 pm, "Jeremy Skinner" <jer...@jeremyskinner.co.uk>
>> > > > > wrote:
>> > > > > > Yep, you'll notice there's no where clause on the query. Its
>> loading
>> > > the
>> > > > > > entire table then performing an in-memory linq query.
>> >
>> > > > > > 2009/1/5 RalyDSM <j...@glmotorsports.net>
>> >
>> > > > > > > are you SURE about the compile thing? When I turn on the
>> show_sql
>> > > > > > > property in NHibernate this is the query that is written:
>> > > > > > > SELECT this_.Id as Id2_0_, this_.Title as Title2_0_ FROM
>> [Product]
>> > > > > > > this_
>> >
>> > > > > > > On Jan 5, 3:04 pm, "Jeremy Skinner" <
>> jer...@jeremyskinner.co.uk>
>> > > > > > > wrote:
>> > > > > > > > I don't think this is an issue with the Repository, rather
>> an
>> > > issue
>> > > > > with
>> > > > > > > > Linq to NHibernate. The VB and C# compilers (unhelpfully)
>> create
>> > > > > > > expression
>> > > > > > > > trees differently. My guess is the Linq to NHibernate code
>> does
>> > > not
>> > > > > parse
>> > > > > > > VB
>> > > > > > > > expression trees correctly (I can't verify this as I don't
>> have
>> > > VB
>> > > > > > > installed
>> > > > > > > > on this machine).
>> >
>> > > > > > > > You don't want to be calling where.Compile() - this causes
>> the
>> > > > > expression
>> > > > > > > > tree to be compiled into a delegate and can no longer be
>> > > translated
>> > > > > into
>> > > > > > > SQL
>> > > > > > > > - instead this ends up loading the entire table into your
>> > > application
>> > > > > and
>> > > > > > > > then doing an *in-memory* filter (bypassing Linq to
>> NHibernate's
>> > > > > > > expression
>> > > > > > > > tree parsing).
>> > > > > > > > Jeremy
>> > > > > > > > 2009/1/5 James Gregory <jagregory....@gmail.com>
>> >
>> > > > > > > > > That's very interesting. Unfortunately, the bits in the
>> > > Framework
>> > > > > > > > > project are rather neglected, so there may very-well be a
>> bug
>> > > in
>> > > > > > > > > there. I need to investigate this before I can pass
>> judgement
>> > > > > though.
>> >
>> > > > > > > > > On 1/5/09, RalyDSM <j...@glmotorsports.net> wrote:
>> >
>> > > > > > > > > > I think I might have found a bug, but I'm not really
>> sure. It
>> > > > > could
>> > > > > > > be
>> > > > > > > > > > a syntax error on my part, but the compiler isn't
>> catching.
>> > > > > Anyway,
>> > > > > > > > > > here is what I'm trying to do. Basically I've written my
>> own
>> > > > > > > > > > repository class that essentially just wraps the Fluent
>> > > > > Repository
>> > > > > > > > > > class. So here is the relevant code:
>> >
>> > > > > > > > > > Public Class GenericRepository(Of T As IHasIntId)
>> >
>> > > > > > > > > >     Private _fluentRepos As
>> > > > > FluentNHibernate.Framework.IRepository
>> >
>> > > > > > > > > >     Public Sub New(ByVal FluentRepository As
>> > > > > > > > > > FluentNHibernate.Framework.IRepository)
>> > > > > > > > > >         _fluentRepos = FluentRepository
>> > > > > > > > > >     End Sub
>> >
>> > > > > > > > > >     Private Sub New()
>> >
>> > > > > > > > > >     End Sub
>> >
>> > > > > > > > > >     Public Function GetById(ByVal Id As Integer) As T
>> >
>> > > > > > > > > >         Return Query(Function(x As T) (x.Id =
>> > > Id)).FirstOrDefault
>> >
>> > > > > > > > > >     End Function
>> >
>> > > > > > > > > >     Public Function Query(ByVal w As Expression(Of
>> > > System.Func(Of
>> > > > > T,
>> > > > > > > > > > Boolean))) As IList(Of T)
>> >
>> > > > > > > > > >         Return _fluentRepos.Query(Of T)(w).ToList()
>> >
>> > > > > > > > > >     End Function
>> >
>> > > > > > > > > > End Class
>> >
>> > > > > > > > > > Then I wrote two unit tests, one that would pass in an
>> > > > > > > > > > InMemoryRepository and one that would use an actual
>> > > NHibernate
>> > > > > > > session
>> > > > > > > > > > to hit the real database.
>> >
>> > > > > > > > > > here they are:
>> >
>> > > > > > > > > >   <TestMethod()> Public Sub InMemoryTest()
>> >
>> > > > > > > > > >         Dim inmemRepos As New InMemoryRepository()
>> >
>> > > > > > > > > >         Dim p As New Product()
>> > > > > > > > > >         Dim id As Integer = 5
>> > > > > > > > > >         p.Id = id
>> > > > > > > > > >         p.Title = "my product"
>> >
>> > > > > > > > > >         inmemRepos.Save(p)
>> >
>> > > > > > > > > >         Dim genRepos As New GenericRepository(Of
>> > > > > Product)(inmemRepos)
>> >
>> > > > > > > > > >         Dim foundP = genRepos.GetById(id)
>> >
>> > > > > > > > > >         Assert.AreEqual(p.Title, foundP.Title)
>> >
>> > > > > > > > > >     End Sub
>> >
>> > > > > > > > > >    <TestMethod()> Public Sub DatabaseTest()
>> >
>> > > > > > > > > >         Dim session =
>> > > > > NHibernateSessionManager.Instance.GetSession()
>> >
>> > > > > > > > > >         Dim flRepos As New Repository(session)
>> > > > > > > > > >         Dim genRepos As New GenericRepository(Of
>> > > > > Product)(flRepos)
>> >
>> > > > > > > > > >         Dim id As Integer = 1
>> >
>> > > > > > > > > >         Dim p = genRepos.GetById(id)
>> >
>> > > > > > > > > >         Assert.IsNotNull(p)
>> > > > > > > > > >         Assert.AreEqual(id, p.Id)
>> >
>> > > > > > > > > >     End Sub
>> >
>> > > > > > > > > > The InMemoryTest passed, and the DatabaseTest failed.
>> The
>> > > > > exception
>> > > > > > > > > > from the DatabaseTest was a type conversion, from int to
>> > > product
>> > > > > (or
>> > > > > > > > > > maybe the other way around.) I was able to "fix" it
>> though.
>> > > In
>> > > > > the
>> > > > > > > > > > Fluent NHibernate code I changed the Query method on the
>> > > > > Repository
>> > > > > > > > > > class from:
>> >
>> > > > > > > > > > return _session.Linq<T>().Where(where).ToArray();
>> >
>> > > > > > > > > > to
>> >
>> > > > > > > > > > return
>> _session.Linq<T>().Where(where.Compile()).ToArray();
>> >
>> > > > > > > > > > Now both tests pass. All of the unit tests in the Fluent
>> > > > > NHibernate
>> > > > > > > > > > project pass either way.
>> >>
>>
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Fluent NHibernate" group.
To post to this group, send email to fluent-nhibernate@googlegroups.com
To unsubscribe from this group, send email to 
fluent-nhibernate+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/fluent-nhibernate?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to