私はLinqでこの問題を解決する方法についてすべて混乱しています。私は実用的なソリューションを持っていますが、それを行うためのコードは、私が考えてあまりにも複雑で、円形である:LinqとMVC2アプリケーションでオブジェクトのネストされたチェーンを取得する方法は?
私は、次の表(簡体字)を持つデータベースを照会したいMVC 2のタイムシートアプリケーションを持っている:
プロジェクトは、多くのタスクを持つことができ、タスクが多くtimesegmentsを持つことができます。プロジェクト タスク TimeSegment
関係は次のとおりです。
これをさまざまな方法で照会できる必要があります。例は次のとおりです。ビューは、テーブル内のプロジェクトのリストを表示するレポートです。各プロジェクトのタスクがリストされ、そのタスクで作業された時間数の合計が続きます。 timeegmentオブジェクトは時間を保持するものです。ここで
ビューです:私が述べたように、この作品、
再びpublic List<TimeSegment> GetTimeSegments(int customerId, string startdate, string enddate)
{
var timeSegments = _repository.TimeSegments
.Where(timeSegment => timeSegment.Customer.CustomerId == customerId)
.Where(timeSegment => timeSegment.DateObject.Date >= DateTime.Parse(startdate) &&
timeSegment.DateObject.Date <= DateTime.Parse(enddate));
return timeSegments.ToList();
}
public List<Project> GetProjects(List<TimeSegment> timeSegments)
{
var projectGroups = from timeSegment in timeSegments
group timeSegment by timeSegment.Task
into g
group g by g.Key.Project
into pg
select new
{
Project = pg.Key,
Tasks = pg.Key.Tasks
};
List<Project> projectList = new List<Project>();
foreach (var group in projectGroups)
{
Project p = group.Project;
foreach (var task in p.Tasks)
{
task.CurrentTimeSegments = timeSegments.Where(ts => ts.TaskId == task.TaskId).ToList();
p.CurrentTasks.Add(task);
}
projectList.Add(p);
}
return projectList;
}
、:
[HttpPost]
public ActionResult MonthlyReports(FormCollection collection)
{
MonthlyReportViewModel vm = new MonthlyReportViewModel();
vm.StartDate = collection["StartDate"];
vm.EndDate = collection["EndDate"];
int customerId = Int32.Parse(collection["Customers"]);
List<TimeSegment> allTimeSegments = GetTimeSegments(customerId, vm.StartDate, vm.EndDate);
vm.Projects = GetProjects(allTimeSegments);
vm.Employee = "Alla";
vm.Customer = _repository.GetCustomer(customerId);
vm.TotalCost = vm.Projects.SelectMany(project => project.CurrentTasks).Sum(task => task.Cost); //Corresponds to above foreach
vm.TotalHours = vm.Projects.SelectMany(project => project.CurrentTasks).Sum(task => task.TaskHours);
vm.TotalCostAndVAT = vm.TotalCost * 1.25;
vm.VAT = vm.TotalCost * 0.25;
return View("MonthlyReport", vm);
}
そして "ヘルパー" 方法:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Report.Master" Inherits="System.Web.Mvc.ViewPage<Tidrapportering.ViewModels.MonthlyReportViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Månadsrapport
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h1>
Månadsrapport</h1>
<div style="margin-top: 20px;">
<span style="font-weight: bold">Kund: </span>
<%: Model.Customer.CustomerName %>
</div>
<div style="margin-bottom: 20px">
<span style="font-weight: bold">Period: </span>
<%: Model.StartDate %> - <%: Model.EndDate %>
</div>
<div style="margin-bottom: 20px">
<span style="font-weight: bold">Underlag för: </span>
<%: Model.Employee %>
</div>
<table class="mainTable">
<tr>
<th style="width: 25%">
Projekt
</th>
<th>
Specifikation
</th>
</tr>
<% foreach (var project in Model.Projects)
{
%>
<tr>
<td style="vertical-align: top; padding-top: 10pt; width: 25%">
<%:project.ProjectName %>
</td>
<td>
<table class="detailsTable">
<tr>
<th>
Aktivitet
</th>
<th>
Timmar
</th>
<th>
Ex moms
</th>
</tr>
<% foreach (var task in project.CurrentTasks)
{%>
<tr class="taskrow">
<td class="task" style="width: 40%">
<%: task.TaskName %>
</td>
<td style="width: 30%">
<%: task.TaskHours.ToString()%>
</td>
<td style="width: 30%">
<%: String.Format("{0:C}", task.Cost)%>
</td>
</tr>
<% } %>
</table>
</td>
</tr>
<% } %>
</table>
<table class="summaryTable">
<tr>
<td style="width: 25%">
</td>
<td>
<table style="width: 100%">
<tr>
<td style="width: 40%">
Totalt:
</td>
<td style="width: 30%">
<%: Model.TotalHours.ToString() %>
</td>
<td style="width: 30%">
<%: String.Format("{0:C}", Model.TotalCost)%>
</td>
</tr>
</table>
</td>
</tr>
</table>
<div class="price">
<table>
<tr>
<td>Moms: </td>
<td style="padding-left: 15px;">
<%: String.Format("{0:C}", Model.VAT)%>
</td>
</tr>
<tr>
<td>Att betala: </td>
<td style="padding-left: 15px;">
<%: String.Format("{0:C}", Model.TotalCostAndVAT)%>
</td>
</tr>
</table>
</div>
</asp:Content>
は、ここでアクションメソッドですもちろん、実際には複雑で、私がコーディングしていても、それを見て自分自身を混乱させてしまいます。私は、私が望むものを達成するためのもっと簡単な方法がなければならないと感じています。基本的に私が達成したいものを見ることができます:
私はプロジェクトのコレクションを取得したいと思います。各プロジェクトには関連するタスクの集まりがあるはずです。また、各タスクには、指定された期間の関連するタイムセグメントのコレクションが含まれている必要があります。選択したプロジェクトとタスクは、この期間のタイムセグメントを持つプロジェクトとタスクでなければならないことに注意してください。私はこの期間内にタイムセグメントを持たないプロジェクトやタスクをすべて望んでいません。
GetProjects()メソッドのようなLinqクエリのグループがこれを達成しているようですが(これは日付などの条件が適用されるように拡張されている場合)、これを返してビューに渡すことはできません。それは匿名のオブジェクトです。私もそのようなクエリで特定の型を作成しようとしましたが、その周りに私の頭をラップすることができませんでした...
私は行方不明とこれを達成するためのいくつかのより簡単な方法があります。最終的にもいくつかの異なるクエリを実行できる必要があります。
「CurrentTimeSegments」プロパティなどで解決した方法も本当に好きではありません。これらのプロパティは実際には最初のモデルオブジェクトには存在しません。ネストされたオブジェクトチェーンの各部分に対してフィルタリングされた結果を配置するために部分クラスに追加しました...
アイデア?
UPDATE:How do I create a nested group-by dictionary using LINQ?:
私はこれらの線に沿って何かを探していますだと思い。それがこのようなものであれば、私は試したが失敗したので、私の問題にそれを翻訳する助けに本当に感謝しています。しかし、私はこの戦略についてはオフになっているかもしれません(正直言って、私はこのような質問が予想されるより複雑です)、もしそうなら、私に教えてください!
更新2:Jon Skeet(文字通り、私の問題に翻訳されていない)の例を試してみると、Dictionaryタイプは得られないので、上記のリンクに関しては、まったく指定する...コンパイラは変換できないと言っています。そして、この結果はViewModelとしてViewに渡されなければならないので、返す特定の型を持つ必要があります。
ちょうど側の注意点一般的なコードの品質に...代わりにIListをまたはIEnumerableをを使用し、パブリックメソッドやプロパティにリストを返すことはありません:) –