当我更改select子句以选择新模型时,为什么这个linq查询失败

时间:2017-11-27 07:09:45

标签: c# linq asp.net-mvc-5 entity-framework-6 ado.net-entity-data-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());

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

  

发生了'System.NotSupportedException'类型的异常   EntityFramework.SqlServer.dll但未在用户代码中处理。

     

附加信息:实体或复杂类型   “HotelApp.Models.Room”无法在LINQ to Entities中构建   查询。

P.S,这是我的Room课程供参考:

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; }
}

2 个答案:

答案 0 :(得分:1)

因为您在这里使用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#对象列表。

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());

答案 1 :(得分:0)

原因Room是您的映射实体之一,不允许投射到映射实体。您必须将DTO或项目用于匿名类型。