Marc Wittke
Marc Wittke

Reputation: 3155

NHibernate and LINQ - InvalidOperationException: "Could not find entity named ..."

Have a look at the following tests:

[TestMethod]
public void CanRead()
{
    using (ISession session = OpenSession())
    {
        var criteria = session.CreateCriteria(typeof(Action));
        var result = criteria.List<Action>();
        Assert.IsTrue(result.Count > 0);
    }
}

[TestMethod]
public void CanReadWithLinq()
{
    using (ISession session = OpenSession())
    {
        IEnumerable<Action> actionQuery = from action in session.Linq<Action>() 
                                          where action.CreatedOn < DateTime.Now
                                          select action;
        List<Action> actions = actionQuery.ToList();
        Assert.IsNotNull(actions);
        Assert.IsTrue(actions.Count > 0);
    }
}

First one runs, so I assume that the mapping is correct (using NHibernate.Attributes in the Action class). Test two fails with the exception:

System.InvalidOperationException: Could not find entity named: BOM.Domain.Action.

It turns out, that every linq expression that uses the entity in the where condition fails with this exception. Removing the where will make it pass, but this is not what I want to achieve, of course. What am I missing? Why is there this exception?


Update:

I created a separate project as follows.

The domain object:

namespace Domain
{
    public class TestEntity
    {
        public Guid Id { get; set; }
        public DateTime CreatedOn { get; set; }
    }
}

The mapping document:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class entity-name="T_TestEntity" name="Domain.TestEntity, Domain" lazy="false">
    <id name="Id" />
    <property name="CreatedOn" column="CreatedOn" />
  </class>
</hibernate-mapping>

Unit test initialization creates a SQL CE database file, which looks to be fine. Tests are quite similar, and I've got the same behavior as before: The fetching with ICriteria works fine, the fetching with Linq works fine until I add a condition that is related to the domain object. Same InvalidOperationException as before, here the stack trace:

Test method Tests.ReadTests.CanReadWithLinq threw exception: System.InvalidOperationException: Could not find entity named: Domain.TestEntity. at NHibernate.Linq.Util.CriteriaUtil.GetRootType(CriteriaImpl criteria) at NHibernate.Linq.Util.CriteriaUtil.GetRootType(ICriteria criteria) at NHibernate.Linq.Visitors.MemberNameVisitor.IsRootEntity(EntityExpression expr) at NHibernate.Linq.Visitors.MemberNameVisitor.VisitEntity(EntityExpression expr) at NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) at NHibernate.Linq.Visitors.NHibernateExpressionVisitor.VisitPropertyAccess(PropertyAccessExpression expr) at NHibernate.Linq.Visitors.MemberNameVisitor.VisitPropertyAccess(PropertyAccessExpression expr) at NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) at NHibernate.Linq.Visitors.MemberNameVisitor.GetMemberName(ICriteria rootCriteria, Expression expr) at NHibernate.Linq.Visitors.BinaryCriterionVisitor.VisitPropertyAccess(PropertyAccessExpression expr) at NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) at NHibernate.Linq.Visitors.BinaryCriterionVisitor.GetBinaryCriteria(ICriteria rootCriteria, ISession session, BinaryExpression expr, ComparePropToValue comparePropToValue, ComparePropToProp comparePropToProp, CompareValueToCriteria compareValueToCriteria, ComparePropToCriteria comparePropToCriteria) at NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitBinaryCriterionExpression(BinaryExpression expr) at NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitBinary(BinaryExpression expr) at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp) at NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) at NHibernate.Linq.Visitors.ExpressionVisitor.VisitLambda(LambdaExpression lambda) at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp) at NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) at NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitUnary(UnaryExpression expr) at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp) at NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) at NHibernate.Linq.Visitors.WhereArgumentsVisitor.GetCriterion(ICriteria rootCriteria, ISession session, Expression expression) at NHibernate.Linq.Visitors.RootVisitor.HandleWhereCall(MethodCallExpression call) at NHibernate.Linq.Visitors.RootVisitor.VisitMethodCall(MethodCallExpression expr) at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp) at NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp) at NHibernate.Linq.Visitors.NHibernateQueryTranslator.Translate(Expression expression, QueryOptions queryOptions) at NHibernate.Linq.NHibernateQueryProvider.TranslateExpression(Expression expression) at NHibernate.Linq.NHibernateQueryProvider.Execute(Expression expression) at NHibernate.Linq.Query1.GetEnumerator() at System.Linq.Enumerable.FirstOrDefault<TSource>(IEnumerable1 source) at Tests.ReadTests.CanReadWithLinq() in ReadTests.cs: line 52.

Upvotes: 0

Views: 1535

Answers (2)

Marc Wittke
Marc Wittke

Reputation: 3155

Solved it after fetching the NHibernate and NHibernate Contrib sources and stepping through: I have to provide the entity name from the database when creating the INHibernateQueryable.

IEnumerable<TestEntity> query = from testEntity in session.Linq<TestEntity>("T_TestEntity") 
    where testEntity.CreatedOn < DateTime.Now
    select testEntity;

I'm still unsure if this is the final solution.


Update

The mapping document defined the entity name instead of the table name. This resulted in a correct schema when exporting and it was also capable of handling the existing schema. However, it behaves different wwith Linq. The correct mapping definition would be:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class table="T_TestEntity" name="Domain.TestEntity, Domain">
    <id name="Id" />
    <property name="CreatedOn" column="CreatedOn" />
  </class>
</hibernate-mapping>

or (when using the attribute mapping of NHibernate Contrib):

[Class(Name = "Domain.TestEntity, Domain", Table = "T_TestEntity")]

Upvotes: 0

TheBoubou
TheBoubou

Reputation: 19933

I think it's a problem with the XML mapping file. Could you check your file Action.hbm.xml, do "F4" and set "Build Action" to "Embedded Resource".

Upvotes: 1

Related Questions