开发者

Seeking recommendation for 3-tiered LINQ Query in Entity Framework

开发者 https://www.devze.com 2023-02-05 15:20 出处:网络
I currently have a LINQ query that is correctly retrieving all relevant poll questions and their associated responses.In this query, I\'m using the .Include() method to retrieve the responses.I like t

I currently have a LINQ query that is correctly retrieving all relevant poll questions and their associated responses. In this query, I'm using the .Include() method to retrieve the responses. I like this approach because it makes the code in my View simple -- basically I have a @foreach for the responses nested inside a @foreach for the questions.

Now, I'd like to add response-specific information such as # of votes today, # of votes this week and # of votes overall. Again, these would be retrieved and displayed for each response of 开发者_如何学Ceach question.

Is there an efficient LINQ solution that would allow me to continue using my .Include() method and my nested @foreach loops or do I need to scrap the .Include() method and use joins to pull everything together?

If it matters for performance reasons, this is being written in .net MVC-3.

Thanks in advance for your opinions/suggestions.


I like this approach because it makes the code in my View simple -- basically I have a @foreach for the responses nested inside a @foreach for the questions.

Personally I wouldn't be satisfied with this. Why writing loops in your view when you can use Display Temapltes? As far as your question about including the # of votes today, # of votes this week and # of votes overall is concerned the answer, as always, is to use a view model which is specifically tailored to the needs of the view:

public class QuestionViewModel
{
    public int VotesToday { get; set; }
    public int VotesThisWeek { get; set; }
    public int TotalVotes { get; set; }
    public IEnumerable<ResponseViewModel> { get; set; }
}

then you would pass an IEnumerable<QuestionViewModel> to your view and it will look like this:

@model IEnumerable<AppName.Models.QuestionViewModel>
@Html.DisplayForModel()

and in ~/Views/Shared/DisplayTemplates/QuestionViewModel.cshtml

@model AppName.Models.QuestionViewModel
<div>@Model.VotesToday</div>
<div>@Model.VotesThisWeek</div>
<div>@Model.TotalVotes</div>
@Html.DisplayFor(x => x.ResponseViewModel)

and in ~/Views/Shared/DisplayTemplates/ResponseViewModel.cshtml:

@model AppName.Models.ResponseViewModel
<div>@Model.Body</div>

Now, that's a clean view.

Let's move to the controller now:

public class QuestionsController: Controller
{
    private readonly IQuestionsRepository _repository;
    public QuestionsController(IQuestionsRepository _repository)
    {
        _repository = repository;
    }

    public ActionResult Index()
    {
        IEnumerable<Question> model = _repository.GetQuestions();
        IEnumerable<QuestionViewModel> viewModel = Mapper
            .Map<IEnumerable<Question>, IEnumerable<QuestionViewModel>>(model);
        return View(viewModel);
    }
}

Here we have abstracted the data access away into a repository so that the controller should never know anything about EF or whatever data access technology you are using. A controller should only know about your model, your view model and abstraction of how to manipulate the model (in this case the repository interface).

As far as the conversion between the your model and the view model is concerned you could use AutoMapper (the Mapper.Map<TSource, TDest> part in my example).

As far as the repository is concerned, that's an implementation detail: whether you perform one or three queries to your database it's up to you. All that's needed is that you are capable of aggregating the required information.

0

精彩评论

暂无评论...
验证码 换一张
取 消