0

This question is related to this

  1. I have decided to change the Generic Repository pattern and used a specific repository for each entity. However I just cant find how to make it work because in my html I need to show some fields from related entities.

  2. Is it better to replace Ienumerable with Iqueryable?

Repository Interface

 public interface IApplicantPositionRepository : IDisposable
    {
        IEnumerable<ApplicationPositionHistory> GetApplicationPositionHistories(int applicantId, int positionId);
                   void Save();
    }

Repository Interface Implementation.

public IEnumerable<ApplicationPositionHistory> GetApplicationPositionHistories(int applicantId, int positionId)
        {
            return context.ApplicationsPositionHistory.Where(d => d.applicantPosition.ApplicantID == applicantId && d.applicantPosition.PositionID == positionId);
        }

Controller Method

public ViewResult History(int applicantId, int positionId)
        {
            var history=applicantPositionRepository.GetApplicationPositionHistories(applicantId, positionId);
            return View(history);
        }

Html.

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.applicantPosition.Applicant.name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.applicantPosition.Position.name)
        </td>
Community
  • 1
  • 1
Luis Valencia
  • 32,619
  • 93
  • 286
  • 506
  • I used this tutorial to implement the repository. http://www.asp.net/entity-framework/tutorials/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application – Luis Valencia Oct 27 '11 at 14:19

2 Answers2

0

Personally I like IList<T> but thats a personal choice of course

To include a related table simply do (this syntax of not using a string for RelatedEntityName like .Include("RelatedEntityName") I think was added in 4.1 if I recall correctly:

 return context.ApplicationsPositionHistory.Where(d => d.applicantPosition.ApplicantID == applicantId && d.applicantPosition.PositionID == positionId).Include(o=>o.RelatedEntityName);

Never return IQueryable from a repository. It's not easily testable since this is very provider specific.

I would also create separate methods if the caller does not require additional details either.

Adam Tuliper
  • 29,982
  • 4
  • 53
  • 71
  • Not really. You can easily call List.AsQueryable() – Dismissile Oct 27 '11 at 14:32
  • I have this error. Are you sure the syntax is correct? 'System.Linq.IQueryable' does not contain a definition for 'Include' and no extension method 'Include' accepting a first argument of type 'System.Linq.IQueryable' could be found (are you missing a using directive or an assembly reference?) I already have System.LINQ there. – Luis Valencia Oct 27 '11 at 14:47
  • 1
    Make sure you have using System.Data.Entity and using System.Linq using statements at the top of your class. – Dismissile Oct 27 '11 at 14:52
  • @Dismissile think I missed your point here. The fact you can create a Queryable from a list has nothing at all to do with the fact that IQueryable providers operate differently from one another and hence difficult to test exactly as your mock implementation can differ from a real implementation. this is well known, and a specific recommendation on a repository - not one Im making up : ) – Adam Tuliper Oct 27 '11 at 18:12
  • Adam, return type should not be a matter of personal taste :) Best practice (no only for repository, but for all classes and especially interfaces) is to use the most unspecific class possible. So, when you are not requiring something special from IList, you just want to do foreach, you should use IEnumerable. – rouen Oct 28 '11 at 08:03
  • @rouen Return type is definitely a matter of taste - simply see the various arguments on the net for both ways. Some even prefer IQueryable in situations, some are very against it. Some prefer IList, some IEnumerable. You cant reference by index in IEnumerable without converting to a list first. If you have other layers that implement paging on the collection and remove items from it, use a list. If you want it immutable, those prefer IEnumerable. In general - I prefer IList in my apps for consistency and don't care if the caller (in my cases) can add/remove from their results. That's not – Adam Tuliper Oct 28 '11 at 15:28
  • saying I don't understand your point - but I believe there is a preference here that surely plays a part. – Adam Tuliper Oct 28 '11 at 15:28
  • see what I mean : ) supports IList: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/eeeff450-cc69-4240-9f1f-76866057918e/ against IList http://stuffbytheway.blogspot.com/2009/02/prefer-ienumerable-to-ilist-for-public.html – Adam Tuliper Oct 28 '11 at 15:49
0

To answer your second question:

It is definitely preferable to use IQueryable instead of IEnumerable. Doing that you can do things like this:

Controller:
public ActionResult Index(int page = 1, int pageSize = 10)
{
    IQueryable<Entity> items = repository.GetEntities();

    items = items.ApplyPaging(page, pageSize);

    return View(items);
}

You could create an extension method off of IQueryable called ApplyPaging that looks like:

public static class QueryableExtensions
{
    public static IQueryable<T> ApplyPaging<T>(this IQueryable<T> source, int page = 1, int pageSize = 10)
    {
        return source.Skip((page - 1) * pageSize).Take(pageSize);
    }
}

If it was IEnumerable then the paging could be done by the client instead of the database building the query correctly.

Dismissile
  • 32,564
  • 38
  • 174
  • 263
  • This is a well debated issue. heres a good one to start: http://stackoverflow.com/questions/718624/to-return-iqueryablet-or-not-return-iqueryablet Mark's no slouch : ) – Adam Tuliper Oct 27 '11 at 18:14