流畅的NHibernate,自动映射器投影无法转换为System.Linq.IQueryable`1 [System.Object []]

时间:2016-02-18 21:11:04

标签: c# fluent-nhibernate automapper projection

自动映射器投影存在奇怪问题。我有以下实体:

public class BankEntity
{
    public BankEntity()
    {
        Customers = new List<CustomerEntity>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Town { get; set; }
    public IList<CustomerEntity> Customers { get; set; }
}

public class CustomerEntity
{
    public CustomerEntity()
    {
        Accounts = new List<BankAccountEntity>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public IList<BankAccountEntity> Accounts { get; set; }
}

public class BankAccountEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Balance { get; set; }
}

使用以下视图:

public class BankView
{
    public BankView()
    {
        Customers = new List<CustomerView>();
    }

    public int Id { get; set; }
    public string Name { get; set; }

    public IList<CustomerView> Customers { get; set; }
}

public class CustomerView
{
    public int Id { get; set; }
    public string Name { get; set; }
}

使用以下视图映射:

AutoMapper.Mapper.CreateMap<BankEntity, BankView>();
AutoMapper.Mapper.CreateMap<CustomerEntity, CustomerView>();

我有一个包装nhibernate会话的repo对象。使用以下内容时:

_repoContext.First<BankEntity, BankView>(a => true);

我收到以下错误:

Object of type 'System.Linq.EnumerableQuery`1[ExampleApp.BankView]' cannot be converted to type 'System.Linq.IQueryable`1[System.Object[]]'.

第一种方法是:

public TP First<TE, TP>(Expression<Func<TE, bool>> exp)
{
    return Session.Query<TE>().Where(exp).Project().To<TP>().AsQueryable().First();
}

如果我没有子列表(即BankView中的客户),它将返回正常。

我添加了AsQueryable以尝试避免此问题。我无法弄清楚为什么它不会映射CustomerViews的子列表。

修改

堆栈跟踪:

   at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast)
   at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
   at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
   at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Delegate.DynamicInvokeImpl(Object[] args)
   at System.Delegate.DynamicInvoke(Object[] args)
   at NHibernate.Linq.DefaultQueryProvider.ExecuteQuery(NhLinqExpression nhLinqExpression, IQuery query, NhLinqExpression nhQuery)
   at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
   at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.First[TSource](IQueryable`1 source)
   at NHibernateRepo.Repos.RepoSplit`2.First[TE,TP](Expression`1 exp) in d:\Development\NHibernateRepoProject\NHibernateRepo\Repos\Repo.cs:line 117

nhibernate SQL输出:

NHibernate: select customers1_.Id as col_0_0_, customers1_.Id as col_1_0_, customers1_.Name as col_2_0_, bankentity0_.Id as col_3_0_, bankentity0_.Id as col_4_0_, bankentity0_.Name as col_5_0_ from [BankEntity] bankentity0_ left outer join [CustomerEntity] customers1_ on bankentity0_.Id=customers1_.BankEntity_id where @p0=1 ORDER BY CURRENT_TIMESTAMP OFFSET 0 ROWS FETCH FIRST 1 ROWS ONLY;@p0 = True [Type: Boolean (0)]

编辑2

作为一个想法,我已将bankAccountEntity添加到视图中,因此更新后的视图如下所示:

public class BankView
{
    public BankView()
    {
        Customers = new List<CustomerView>();
    }

    public int Id { get; set; }
    public string Name { get; set; }

    public IList<CustomerView> Customers { get; set; }
}

public class CustomerView
{
    public CustomerView()
    {
        Accounts = new List<BankAccountView>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public IList<BankAccountView> Accounts { get; set; }

}

public class BankAccountView
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Balance { get; set; }
}
}

我得到的例外情况有所改变:

A first chance exception of type 'System.InvalidOperationException' occurred in System.Core.dll

Additional information: Code supposed to be unreachable

堆栈跟踪:

at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression node)
at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.AddArguments(IArgumentProvider expressions)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.MemberAssignmentRewriter..ctor(MemberAssignment binding, StackSpiller spiller, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.BindingRewriter.Create(MemberBinding binding, StackSpiller spiller, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteMemberInitExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.Rewrite[T](Expression`1 lambda)
at System.Linq.Expressions.Expression`1.Accept(StackSpiller spiller)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteLambdaExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression node)
at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.AddArguments(IArgumentProvider expressions)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression node)
at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.AddArguments(IArgumentProvider expressions)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression node)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression node)
at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.AddArguments(IArgumentProvider expressions)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.MemberAssignmentRewriter..ctor(MemberAssignment binding, StackSpiller spiller, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.BindingRewriter.Create(MemberBinding binding, StackSpiller spiller, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteMemberInitExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.Rewrite[T](Expression`1 lambda)
at System.Linq.Expressions.Expression`1.Accept(StackSpiller spiller)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteLambdaExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression node)
at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.AddArguments(IArgumentProvider expressions)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.Add(Expression node)
at System.Linq.Expressions.Compiler.StackSpiller.ChildRewriter.AddArguments(IArgumentProvider expressions)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteMethodCallExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.Rewrite[T](Expression`1 lambda)
at System.Linq.Expressions.Expression`1.Accept(StackSpiller spiller)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteInvocationExpression(Expression expr, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression(Expression node, Stack stack)
at System.Linq.Expressions.Compiler.StackSpiller.Rewrite[T](Expression`1 lambda)
at System.Linq.Expressions.Expression`1.Accept(StackSpiller spiller)
at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator)
at System.Linq.Expressions.Expression`1.Compile()
at NHibernate.Linq.ExpressionToHqlTranslationResults.MergeLambdasAndCompile[TDelegate](IList`1 itemTransformers)
at NHibernate.Linq.ExpressionToHqlTranslationResults..ctor(HqlTreeNode statement, IList`1 itemTransformers, IList`1 listTransformers, IList`1 postExecuteTransformers, List`1 additionalCriteria)
at NHibernate.Linq.IntermediateHqlTree.GetTranslation()
at NHibernate.Linq.Visitors.QueryModelVisitor.GenerateHqlQuery(QueryModel queryModel, VisitorParameters parameters, Boolean root)
at NHibernate.Linq.NhLinqExpression.Translate(ISessionFactoryImplementor sessionFactory, Boolean filter)
at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)
at NHibernate.Engine.Query.QueryExpressionPlan.CreateTranslators(IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)
at NHibernate.Engine.Query.QueryExpressionPlan..ctor(IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory)
at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters)
at NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow)
at NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression)
at NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery)
at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.First[TSource](IQueryable`1 source)
at NHibernateRepo.Repos.RepoSplit`2.First[TE,TP](Expression`1 exp) in d:\Development\NHibernateRepoProject\NHibernateRepo\Repos\Repo.cs:line 117

编辑3

var expression = AutoMapper.Mapper.Engine.CreateMapExpression(typeof (BankEntity), typeof (BankView));

表达式给出:

.New ExampleApp.BankView(){
Id = $dto.Id,
Name = $dto.Name,
Customers = .Call System.Linq.Enumerable.ToList(.Call System.Linq.Enumerable.Select(
        $dto.Customers,
        .Lambda #Lambda1<System.Func`2[ExampleRepo.Models.CustomerEntity,ExampleApp.CustomerView]>))
}

.Lambda    #Lambda1<System.Func`2[ExampleRepo.Models.CustomerEntity,ExampleApp.CustomerView]>(ExampleRepo.Models.CustomerEntity $dto)
{
.New ExampleApp.CustomerView(){
    Id = $dto.Id,
    Name = $dto.Name,
    Accounts = .Call System.Linq.Enumerable.ToList(.Call System.Linq.Enumerable.Select(
            $dto.Accounts,
            .Lambda #Lambda2<System.Func`2[ExampleRepo.Models.BankAccountEntity,ExampleApp.BankAccountView]>))
}
}

.Lambda #Lambda2<System.Func`2[ExampleRepo.Models.BankAccountEntity,ExampleApp.BankAccountView]>(ExampleRepo.Models.BankAccountEntity $dto)
{
.New ExampleApp.BankAccountView(){
    Id = $dto.Id,
    Name = $dto.Name,
    Balance = $dto.Balance
}
}

修改

看起来可能与以下内容有关:

https://nhibernate.jira.com/browse/NH-3043

https://hibernate.atlassian.net/browse/HHH-3356

0 个答案:

没有答案