LINQ中仅支持无参数构造函数并转换为实体

时间:2016-06-09 18:12:47

标签: c# entity-framework linq

我知道这个问题已在这里被多次提出,但它们都没有解决我的问题。

我有2个实体,StaffDTOAppointmentStaffDTO有一个Appointment的集合。 Appointment具有延迟加载的导航属性。

public class StaffDTO {

    public IEnumerable<Appointment> Appointments { get; set; }

}

public class Appointment {

    public virtual Client Client { get; set; }

    public virtual Staff Staff { get; set; }

    public virtual Service Service { get; set; }
}

现在,使用LINQ,我构建了这个查询:

using (var ctx = new ApplicationDbContext())
{
var staff = ctx.Set<Staff>();


var staffs = (from stf in staff
             select new StaffDTO
             {
                 Appointments = stf.StaffAppointments
             }).ToList();
}

这很有效。 但是,当我尝试序列化StaffDTO时,我收到一条错误消息,指出已经处理了上下文。

这是有道理的,因为在序列化对象时,Appointment集合中的每个StaffDTO.Appointments都会读取其延迟加载的属性,但此列表的汇编上下文不存在了。

此处不能选择Appointment类属性不是虚拟(懒惰)。

如何在LINQ查询中加载延迟属性?

我尝试了什么

我尝试使用Appointment所需的属性编写一个AppointmentDTO类并编写这个LINQ:

from stf in staff
select new StaffDTO
{
    Appointments = stf.StaffAppointments.Select(a => new AppointmentDTO(a))
};

然后我得到无参数构造函数异常。

我也尝试编写一个隐式运算符来将约会转换为AppointmentDTO,但我再次从linq获得了强制转换异常。

2 个答案:

答案 0 :(得分:0)

将其更改为Appointments = stf.StaffAppointments.ToList()以立即实现这些对象。

答案 1 :(得分:0)

您需要ToList stf.StaffAppointmentsIEnumerable中的项目是懒惰生成的,这意味着当某人尝试迭代DTO的Appointments时,某些地方需要EF上下文处于活动状态。

除非您可以将DTO的生命周期与上下文的生命周期联系起来(这很尴尬且不必要),否则您应该在实例化DTO时从EF中提取所有数据。

编辑:我错过了您对Appointment实体中其他实体的延迟加载引用的事实。现在的问题是你的StaffDTO实际上并不是DTO。 DTO应该是特定实体中存在的所有数据的静态(优选可序列化)快照。您需要复制输出所有数据,而不仅仅是引用原始实体。您可以手动编写,也可以使用AutoMapper之类的东西来简化操作。