当我将 select 子句更改为 select new Model 时,为什么此 linq 查询失败

Why does this linq query fail when I change the select clause to select new Model

为什么这个查询有效:

var rooms = from m in db.Rooms
                      where
                      m.FK_HotelID == id
                      select m;

            return View(rooms.ToList());

但是这个查询(我从一个名为 'Linqer' 的程序生成的)似乎失败了?

var rooms = from m in db.Rooms
                      where
                      m.FK_HotelID == id
                      select new Room
                      {
                          RoomID = m.RoomID,
                          RoomNumber = m.RoomNumber,
                          RoomType = m.RoomType,
                          FK_HotelID = m.FK_HotelID
                      };

            return View(rooms.ToList());

我需要帮助来查询 return 个 ListRoom 个对象。 我不认为我可以使用匿名类型或 DTO 模型进行查询,因为视图需要 Room 类型的对象。查询确实 return 在 Linqer 程序中产生结果,但是当我尝试在我的 VS2013 项目中获取此视图时,我收到以下错误消息:

An exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll but was not handled in user code.

Additional information: The entity or complex type 'HotelApp.Models.Room' cannot be constructed in a LINQ to Entities query.

P.S,这是我的房间class供参考:

public partial class Room
{
    public Room()
    {
        Bookings = new HashSet<Booking>();
    }
    public int RoomID { get; set; }
    public int RoomNumber { get; set; }
    public string RoomType { get; set; }
    public int? FK_HotelID { get; set; }
    public virtual ICollection<Booking> Bookings { get; set; }
    public virtual Hotel Hotel { get; set; }
}

因为您在这里使用 LINQ To SQL,这意味着该查询被翻译成 SQL,它不知道您的自定义类型。

    var rooms = (from m in db.Rooms
                      where
                      m.FK_HotelID == id
                      select m).ToList();

    var roomsVm = from m in rooms select new Room
                      {
                          RoomID = m.RoomID,
                          RoomNumber = m.RoomNumber,
                          RoomType = m.RoomType,
                          FK_HotelID = m.FK_HotelID
                      };

            return View(roomsVm.ToList());

这里发生的是:

1) 第一个查询转到 SQL 并找到您需要的所有房间。

2)然后翻译成C#对象的List。

3) 此时的第二个查询正在使用 LINQ To Objects,因此可以使用您的自定义模型。


更好的解决方案是创建一个 ViewModel,其中包含您需要的所有字段,例如:

public class RoomViewModel {
    public int RoomId {get;set;}
    public string RoomNumber {get;set;}
    public string HotelName {get;set;}
//and all other properties you need on your View
}

然后将您的 DTO 映射到这个新的 ViewModel:

var roomsVm = from m in rooms select new RoomViewModel
                          {
                              RoomId = m.RoomID,
                              RoomNumber = m.RoomNumber,
                              HotelName = m.Hotel.HotelName
                              //and other properties
                          };

                return View(roomsVm.ToList());

那是因为 Room 是您的映射实体之一,并且不允许投影到映射实体。您将不得不使用 DTO 或项目到匿名类型。