When there is a convert node type before a member access on the left side, BinaryCriterionVistor thinks it needs to change the type of the right side

Description

{(Convert([1001]).ValidDateRange.BeginDate <= 8/25/2008 1:04:27 PM)}

In this expression, which is used by Where, there is a Convert on the the persisted type, the convert is probably due to our use of generics on the expression, however it's followed by two member accesses such that we are indeed comparing two dates. However, BinaryCriterionVistor through visting the sub expression on the left gets when it gets to the Convert node it's ConvertTo property set and then erroneously thinks it needs to use ChangeType on the date on the right side to the persisted type (line 133 of BinaryCriterionVistor.cs)

Environment

None

Activity

Show:

Chris Haines August 7, 2009 at 3:42 AM

I have the same issue - it seems to happen using a comparison on any generic type.

Here is a simple test that proves the error (assuming Repository<T> is some repository base that gives access to the NHibernate Session):

[TestFixture]
public class Class1
{
[Test]
public void ShouldBeAbleToGetItem()
{
var repo = new Repo<Entity1>();
var result = repo.Get();
Assert.That(result != null);
}
}

public class Repo<T> : Repository<T> where T : IMyGenericInterfaceType
{
public T Get()
{
var queryable = Session.Linq<T>();
return queryable.Where(item => item.Id == 1).First();
}
}

public class Entity1 : IMyGenericInterfaceType
{
public int Id { get; set; }
public DateTime Date { get; set; }
}

public class Entity2 : IMyGenericInterfaceType
{
public int Id { get; set; }
public DateTime Date { get; set; }
}

public interface IMyGenericInterfaceType
{
int Id { get; set; }
DateTime Date { get; set; }
}

Tuna Toksoz July 22, 2009 at 5:16 PM

I need a simple test.

Andrew Bullock March 10, 2009 at 4:35 AM

I'm having exactly the same issue, I've abstracted my CRUD methods to a generic base class which adds a Convert() around elements in the lamba, which is then not treated correctly by the Visitors (possibly AssociationVisitor) Here's some of my code http://stackoverflow.com/questions/629480/strange-linq-to-nhibernate-issue-invalid-cast-from-system-int32

Any chance of a fix for this, or any clues on what to do to begin patching?

Jay Tuley August 25, 2008 at 1:38 PM

I removed the generics from the type, and discovered HasValue was not correct syntax, so i changed them to == null, and it works just fine without generics

public static Expression<Func<PlanVestingRuleset, bool>> WithinValidDateRange([NotNull]DateTime aDate)
{
return Linq.Expr<TData, bool>(v =>
(
v.ValidDateRange.BeginDate==null

 

v.ValidDateRange.BeginDate <= aDate
)
&&
(
v.ValidDateRange.BeginDate == null

 

v.ValidDateRange.EndDate >= aDate
)
);

}
}

but of course still doesn't work again if I add the generics back after fixing the HasValue issue

public static Expression<Func<TData, bool>> WithinValidDateRange<TData>([NotNull]DateTime aDate)
where TData : IValidDateRangedDataItem
{
return Linq.Expr<TData, bool>(v =>
(
v.ValidDateRange.BeginDate==null

 

v.ValidDateRange.BeginDate <= aDate
)
&&
(
v.ValidDateRange.BeginDate == null

 

v.ValidDateRange.EndDate >= aDate
)
);

}
}

Jay Tuley August 25, 2008 at 11:34 AM

We keep criteria types shared using static methods that return expressions. That's where the generics come in:

static public class Expr
{
public static Expression<Func<TData, bool>> WithinValidDateRange<TData>([NotNull]DateTime aDate)
where TData: IValidDateRangedDataItem
{
return Linq.Expr<TData, bool>(v =>
(
!v.ValidDateRange.BeginDate.HasValue

 

v.ValidDateRange.BeginDate <= aDate
)
&&
(
! v.ValidDateRange.EndDate.HasValue

 

v.ValidDateRange.EndDate >= aDate
)
);

}
}

then we use it like this tDB.PlanVestingRulesets.Where(Expr.WithinValidDateRange<PlanVestingRuleset>(asOfDate))

Details

Assignee

Reporter

Components

Affects versions

Priority

Who's Looking?

Open Who's Looking?

Created August 25, 2008 at 11:22 AM
Updated August 7, 2009 at 3:42 AM
Who's Looking?