I've looked the question up but nothing I have found is working for me. I created a view in SQL which works when you run it in the Management Studio. When the view is accessed from my MVC Application, EF is returning identical rows instead of rows with different data.
Table: Cars
- [Id]
- [Registration]
- [Make]
- [Model]
Table: Bookings
- [Id]
- [BookingStartDate]
- [BookingEndDate]
- [CarId]
View: CarBookings
SELECT [C].[Id],
[C].[Registration],
[C].[Make],
[C].[Model],
[B].[BookingStartDate],
[B].[BookingEndDate]
FROM [Cars] AS C INNER JOIN [Bookings] AS B ON C.Id = B.CarId
If I run the query in SSMS I get all the expected results, for example:
- Car 1, Booked 12/03/2018
- Car 1, Booked 19/09/2018
When I access the same view from my MVC Application I get:
- Car 1, Booked 12/03/2018
- Car 1, Booked 12/03/2018
Putting a breakpoint onto the controller shows that the results are the same so it's not the presentation layer that's causing it. No filters are applied and there are no conditions at all.
I'm using KendoUI
and returning my results to a Grid
.
Here is my controller code for getting the data:
HomeController.cs
public ActionResult GetBookings([DataSourceRequest] DataSourceRequest request)
{
var bookings = unitOfWork.BookingsRepository.Get();
var result = bookings.ToDataSourceResult(request);
return Json(result, JsonRequestBehavior.AllowGet);
}
My application uses a generic repository. I'm not sure if it's causing the problem but it's worth mentioning. Here is the GET
method from my repository.
DAL/GenericRepository.cs
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
DAL/Context.cs
public DbSet<Bookings> Bookings { get; set; }
DAL/UnitOfWork.cs
private GenericRepository<Bookings> bookingsRepository;
public GenericRepository<Bookings> bookingsRepository
{
get
{
if (this.bookingsRepository == null)
{
this.bookingsRepository = new GenericRepository<Bookings>(context);
}
return bookingsRepository;
}
}
Entity Class
This is the class that represents the view and accesses it using the [Table]
annotation.
namespace MyProject.Models
{
[Table("CarBookings")]
public class Bookings
{
//Car
[Key]
public int Id { get; set; }
public string Registration { get; set; }
public string Make { get; set; }
public string Model { get; set; }
//Booking
public DateTime BookingStartDate { get; set; }
public DateTime BookingEndDateYearOfBuild { get; set; }
}
}
When I searched for answers to this, I read that the view doesn't have an ID
so EF tries to logically order records by unique values and this can sometimes cause problems (source: https://www.itworld.com/article/2833108/development/linq-in--net-returning-duplicate-rows-from-a-working-sql-view--solved-.html).
I adjusted my views select
code as per the above article but it didn't work for me; I still saw duplicates:
SELECT ROW_NUMBER() OVER (ORDER BY Car.Id) AS NID,
Car.Id,
Booking.BookingStartDate
... etc...
FROM Cars AS Car INNER JOIN
Booking AS Booking ON Car.Id = Booking.Car_Id