自动映射器投影存在奇怪问题。我有以下实体:
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
}
}
修改
看起来可能与以下内容有关: