使用EfCore进行多个ProjectTo图层时出错

时间:2019-12-10 14:47:21

标签: c# asp.net-core automapper ef-core-3.0

我正在尝试创建一个“设计指南”以在我的公司中构建其余的api,我希望拥有一个具有Automapper,asp.net核心和ef核心的三层结构。

Database Layer : DbSet Entities
Business Layer : Application Models
Api/Rest/External Layer : Dto Object

我已经成功地做到了以下要点:https://gist.github.com/Angelinsky7/49c86333584e3f9cece44a88e7febd4e

但是正如您所看到的,我需要使用黑客工具才能完成此工作...(https://gist.github.com/Angelinsky7/49c86333584e3f9cece44a88e7febd4e#file-automapper_bug_lambda_projection-cs-L23-L24,(https://gist.github.com/Angelinsky7/49c86333584e3f9cece44a88e7febd4e#file-automapper_bug_lambda_projection-cs-L89)和(https://gist.github.com/Angelinsky7/49c86333584e3f9cece44a88e7febd4e#file-automapper_bug_lambda_projection-cs-L93

public IEnumerable<SubLayer2> _Subs { get; set; } = new HashSet<SubLayer2>();
public ICollection<SubLayer2> Subs => (ICollection<SubLayer2>)_Subs;

cfg.CreateMap<Layer1, Layer2>()
  .ForMember(p => p._Subs, opt => opt.MapFrom(src => src.Subs));
cfg.CreateMap<Layer2, Layer3>()
  .ForMember(p => p.Subs, opt => opt.MapFrom(src => src._Subs));

而且我非常不喜欢它(因为即使这样工作,在更复杂的senarii中,它也不再工作)

如果我不做黑客:https://gist.github.com/Angelinsky7/0e26507c07c066376d5a4de8726dd1f2

在具有Layer3作为IEnumerable的InMemory EfCore案例中:(在创建问题之前,我没有这个) Unhandled exception. System.InvalidOperationException: The LINQ expression 'dtoSubLayer2' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync()

在具有Layer3作为IEnumerable的SqlServer EfCore案例中:(我想使用的是) InvalidOperationException: When called from 'VisitLambda', rewriting a node of type 'System.Linq.Expressions.ParameterExpression' must return a non-null value of the same type. Alternatively, override 'VisitLambda' and change it to not visit children of this type.

在所有将Layer3作为ICollection的EfCore中: Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.

我做错了什么?这完全不可能吗?有没有办法让我找到弹出异常并自定义此行为的NullReferenceException或VisitLambda?拥有这种解决方案将是完美的,因为我将完全拥有我想要构建我的REST API的...

源/目的地类型

internal class Layer1 {
  public Int64 Id { get; set; }
  public ICollection<SubLayer1> Subs { get; set; } = new HashSet<SubLayer1>();
}

internal class SubLayer1 {
  public Int64 Id { get; set; }
  public Int64 LayerId { get; set; }
}

internal class Layer2 {
  public Int64 Id { get; set; }
  public ICollection<SubLayer2> Subs { get; set; } = new HashSet<SubLayer2>();
}

internal class SubLayer2 {
  public Int64 Id { get; set; }
}

internal class Layer3 {
  public Int64 Id { get; set; }
  public IEnumerable<SubLayer3> Subs { get; set; } = new HashSet<SubLayer3>();
}

internal class SubLayer3 {
  public Int64 Id { get; set; }
}

映射配置

cfg.CreateMap<Layer1, Layer2>();
cfg.CreateMap<SubLayer1, SubLayer2>();

cfg.CreateMap<Layer2, Layer3>();
cfg.CreateMap<SubLayer2, SubLayer3>();

版本:x.y.z

<PackageReference Include="AutoMapper" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.0" />

预期行为

我应该能够使用ProjectTo Multiple时间来更改图层,而不必使用技巧来完成。而且我应该可以在ICollection和IEnumerable之间进行选择

实际行为

根据实现情况之一,会出现3个异常(大多数情况下是“ VisitLambda” lambda)

复制步骤

https://gist.github.com/Angelinsky7/0e26507c07c066376d5a4de8726dd1f2

感谢所有帮助,并感谢您抽出宝贵的时间!!! (并且很抱歉,如果这是一个efcore问题,但是我在想:“因为我可以在automapper中创建一个“ hack”,也许在这里”)

我之所以来到这里是因为自动映射器团队认为这并不是他们的错误(https://github.com/AutoMapper/AutoMapper/issues/3280

1 个答案:

答案 0 :(得分:0)

似乎自动映射器无法执行我想要的操作。 我的错。 感谢社区的帮助。