Linq lambda join error
I have been following the book Pro ASP.net MVC 2 Framework, which I have found to be quite brilliant. But it's a real learning curve and now I'm stuck.
In the book you build something like the below, which allows for paging.
public ViewResult List([DefaultValue(0)] string cityzip, [DefaultValue(1)] int page)
{
var roomsToShow = roomsRepository.Rooms.Where(x => x.CountryID == cityzip);
var viewModel = new RoomsListViewModel
{
Rooms = roomsToShow.Skip((page - 1) * PageSize).Take(PageSize).ToList(),
PagingInfo = new PagingInfo
{
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = roomsToShow.Count()
}
};
return View(viewModel); // Passed to view as ViewData.Model (or simply Model)
}
I think needed to adapt this, so that I could do a join on the search
public ViewResult List([DefaultValue(0)] string cityzip, [DefaultValue(1)] int page)
{
var roomsToShow = roomsRepository.Rooms.Join(
roomCoordinatesRepository.RoomCoordinates,
room => room.RoomID,
roomCoordinate => roomCoordinate.RoomID,
(room, roomCoordinate) => new { RoomCoordinate = roomCoordinate, Room = room });
var viewModel = new RoomsListViewModel
{
Rooms = roomsToShow.Skip((page - 1) * PageSize).Take(PageSize).ToList(),
PagingInfo = new PagingInfo
{
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = roomsToShow.Count()
}
};
return View(viewModel); // Passed to view as ViewData.Model (or simply Model)
}
...but immediately I get an intellisense error saying -
Cannot implicitly convert type 'System.Collections.Generic.List<AnonymousType#1>'
to 'System.Collections.Generic.IList<MeetingRoom.Domain.Entities.Room>'
. An explicit conversion exists (are you missing a cast?)
I obviously don't understand the code well enough to figure out what is wrong. I'm also feeling a bit out of my depth with this lamda linq stuff
Room is a domain object which is defined as:
namespace MeetingRoom.Domain.Entities
{
[Table(Name = "Rooms")]
public class Room
{
[Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
public int RoomID { get; set; }
[Column] public string Name { get; set; }
[Column] public string Description { get; set; }
[Column] public decimal Price { get; set; }
[Column] public string Category { get; set; }
[Column] public string Pcode { get; set; }
[Column] public int CountryID { get; set; }
public MeetingRooms开发者_StackOverflow.Domain.entities.RoomCoordinate RoomCoordinate { get; set; }
}
}
and represents my Room table. Do I need some sort of parent entity that would represent the join between the Room and Room-co-ordinates table?
The co-ordinates entity looks like this:
namespace MeetingRooms.Domain.entities
{
[Table(Name = "RoomCoordinate")]
public class RoomCoordinate
{
[Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert, Name = "ID")]
public int CoordID { get; set; }
[Column]
public int RoomID { get; set; }
[Column]
public string Coordinates { get; set; }
[Column]
public decimal Latitude { get; set; }
[Column]
public decimal Longitude { get; set; }
}
}
The RoomsListViewModel looks like follows: namespace MeetingRoomsMVC.WebUI.Models { public class RoomsListViewModel { public IList RoomsWithCoordinates { get; set; } public PagingInfo PagingInfo { get; set; }
} }The problem is, in this code
var roomsToShow = roomsRepository.Rooms.Join(
roomCoordinatesRepository.RoomCoordinates,
room => room.RoomID,
roomCoordinate => roomCoordinate.RoomID,
(room, roomCoordinate) => new { RoomCoordinate = roomCoordinate, Room = room });
you're constructing an IEnumerable
of anonymous-type objects: (room, roomCoordinate) => new { RoomCoordinate = roomCoordinate, Room = room }
And then, in the next line you're trying to assing it to a list of Room
.
The problem can be resolved by initially creating an IEnumerable
of the correct item type:
var roomsToShow = roomsRepository.Rooms.Join(
roomCoordinatesRepository.RoomCoordinates,
room => room.RoomID,
roomCoordinate => roomCoordinate.RoomID,
(room, roomCoordinate) => new MeetingRoom.Domain.Entities.Room{ RoomCoordinate = roomCoordinate, Room = room });
(note the class name in the lambda).
Here's my suggestion based on the OP's further description:
1) Create an aggregate class that holds both Room
and RoomCoordinates
info:
public class RoomWithCoordinates
{
public Room Room { get; set; }
public RoomCoordinates Coordinates { get; set; }
}
2) Modify your controller action as follows:
public ViewResult List([DefaultValue(0)] string cityzip, [DefaultValue(1)] int page)
{
var roomsToShow = roomsRepository.Rooms.Join(
roomCoordinatesRepository.RoomCoordinates,
room => room.RoomID,
roomCoordinate => roomCoordinate.RoomID,
(room, roomCoordinate) => new RoomWithCoordinates{ Coordinates = roomCoordinate, Room = room } );
var viewModel = new RoomsListViewModel
{
RoomsWithCoordinates = roomsToShow.Skip((page - 1) * PageSize).Take(PageSize).ToList(),
PagingInfo = new PagingInfo
{
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = roomsToShow.Count()
}
};
return View(viewModel); // Passed to view as ViewData.Model (or simply Model)
}
3) Modify your RoomsListViewModel
class and your view to reflect these changes.
精彩评论