我有一个非常基本的实体框架实体,如下所示:
public class Student
{
public string Given { get; set; }
public string Surname { get; set; }
public ICollection<Address> Addresses { get; set; }
}
我想使用AutoMapper将此实体映射到相应的展平ViewModel,如下所示:
public class StudentViewModel
{
public string Given { get; set; }
public string Surname { get; set; }
public string PhysicalAddressStreet { get; set; }
public string PhysicalAddressCity { get; set; }
public string PhysicalAddressState { get; set; }
public string PostalAddressStreet { get; set; }
public string PostalAddressCity { get; set; }
public string PostalAddressState { get; set; }
}
为此,我尝试了以下映射配置:
CreateMap<Student, StudentViewModel>()
.ForMember(dest => dest.Given, opt => opt.MapFrom(src => src.Given))
.ForMember(dest => dest.Surname, opt => opt.MapFrom(src => src.Surname))
.ForMember(dest => dest.PhysicalAddressStreet, opt => opt.MapFrom(src => src.Addresses.FirstOrDefault(add => add.Type == AddressType.Physical).Street))
.ForMember(dest => dest.PhysicalAddressCity, opt => opt.MapFrom(src => src.Addresses.FirstOrDefault(add => add.Type == AddressType.Physical).City))
.ForMember(dest => dest.PhysicalAddressState, opt => opt.MapFrom(src => src.Addresses.FirstOrDefault(add => add.Type == AddressType.Physical).State))
.ForMember(dest => dest.PostalAddressStreet, opt => opt.MapFrom(src => src.Addresses.FirstOrDefault(add => add.Type == AddressType.Postal).Street))
.ForMember(dest => dest.PostalAddressCity, opt => opt.MapFrom(src => src.Addresses.FirstOrDefault(add => add.Type == AddressType.Postal).City))
.ForMember(dest => dest.PostalAddressState, opt => opt.MapFrom(src => src.Addresses.FirstOrDefault(add => add.Type == AddressType.Postal).State));
问题是,当我使用投影运行此映射时:
studentDbSet.Where(st => st.Id == studentId)
.ProjectTo<TProjection>(_mapper.ConfigurationProvider);
我收到以下错误:
动态SQL错误SQL错误代码= -104令牌未知 - 第14行, 第2栏OUTER
这是一个Firebird错误,似乎在编译Linq to SQL时,生成的查询包含OUTER APPLY
,Firebird不支持。
有没有办法修改我的投影以避免OUTER APPLY
?
据我所知,OUTER APPLY
来自FirstOrDefault()
来电。有没有其他方法可以编写Linq以避免使用它?
编辑以澄清:这是我无法修改实体或数据库架构的情况,因此假设这些是不可触及的。
答案 0 :(得分:0)
我认为你的核心存在建模问题。如果需要物理地址,只需在模型上包含PhysicalAddress属性,并保持该关系。您仍然可以拥有该类型的地址集合。看起来你正在做&#34; FirstOrDefault&#34;,这意味着你只能拥有一个实际地址或只有第一个问题。我猜测你只能拥有一个。
所以只需要一个。在Student模型(和Student表)上,在地址表中有一个FK,&#34; PhysicalAddress&#34;。然后在代码中保存地址的位置,适当地更新PhysicalAddress。封装子集合以便您无法执行任何添加/删除操作有助于。
一旦你在Student上有了PhysicalAddress关系,这个问题变得微不足道,它只是一个普通的映射。
答案 1 :(得分:0)
这是编写避免OUTER APPLY
的LINQ查询的唯一方法(不确定如何将其与AutoMapper
映射,如果你确实需要它,请将该部分留给你):
var query =
from student in studentDbSet
where student.Id == studentId
from physicalAddress in student.Addresses.Where(a => a.Type == AddressType.Physical)
from postalAddress in student.Addresses.Where(a => a.Type == AddressType.Postal)
select new StudentViewModel
{
Given = student.Given,
Surname = student.Surname,
PhysicalAddressStreet = physicalAddress.Street,
PhysicalAddressCity = physicalAddress.City,
PhysicalAddressState = physicalAddress.State,
PostalAddressStreet = postalAddress.Street,
PostalAddressCity = postalAddress.City,
PostalAddressState = postalAddress.State,
};