避免在实体框架预测中应用OUTER

时间:2016-10-04 04:09:13

标签: c# entity-framework linq automapper

我有一个非常基本的实体框架实体,如下所示:

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以避免使用它?

编辑以澄清:这是我无法修改实体或数据库架构的情况,因此假设这些是不可触及的。

2 个答案:

答案 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,
    };