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 -~----------~----~----~----~------~----~------~--~---