經過大量的搜索,閱讀,試驗和錯誤,我找到了一種方法來完成這項工作。
首先,我意識到LINQ表達式不是我需要去的方式。我需要單獨構建行。由於數據具有動態列,因此DBSet無法工作。所以我在SQL中建立了一個Pivot查詢;
DECLARE @cols NVARCHAR (MAX),
@StartDate date = '03/01/2017',
@EndDate date = '03/20/2017',
@Id nvarchar(10) = 1
SELECT @cols = COALESCE (@cols + ',[' + CONVERT(NVARCHAR, entrydate, 106) +
']',
'[' + CONVERT(NVARCHAR, entrydate, 106) + ']')
FROM (SELECT DISTINCT entrydate
FROM EmployeeTask
WHERE entrydate >= @StartDate AND entrydate <= @EndDate
AND EmployeeId = @Id) PV
ORDER BY entrydate DESC
DECLARE @query NVARCHAR(MAX)
SET @query = '
SELECT * FROM (SELECT KeyTask, acceptable, entrydate
FROM EmployeeTask
WHERE EmployeeId = ('+ @Id +')
Group by KeyTask, acceptable, entrydate) x
PIVOT (SUM(acceptable) FOR entrydate IN (' + @cols + ')) p
'
EXEC SP_EXECUTESQL @query
這給了我想要顯示的表,但如何讓它顯示在MVC 6?
首先,我發現this SO post和Petr Vobornik的答案正是我所需要的。我不得不修改它並把它添加到我的控制器:
private static List<Dictionary<string, object>> LoadData(string sqlSelect,
params object[] sqlParameters)
{
var table = new List<Dictionary<string, object>>();
using (var ctx = new DBContext())
{
ctx.Database.GetDbConnection();
ctx.Database.OpenConnection();
using (var cmd = ctx.Database.GetDbConnection().CreateCommand())
{
cmd.CommandText = sqlSelect;
foreach (var param in sqlParameters)
cmd.Parameters.Add(param);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var row = new Dictionary<string, object>();
for (int i = 0; i < reader.FieldCount; i++)
row[reader.GetName(i)] = reader[i];
table.Add(row);
}
if (table == null)
{
var row = new Dictionary<string, object>();
for (int i = 0; i < 1; i++)
row[reader.GetName(i)] = "None";
table.Add(row);
}
}
}
}
return table;
}
if語句用來添加一個空行,這樣仍會生成列表,但它不包含任何內容。這樣,如果查詢不返回任何內容,仍然可以加載一個空視圖(請參閱下面的視圖)。
我說在我的控制器SQL連接:
public IActionResult Index(int id, string datestart, string dateend)
{
HttpContext.Session.SetInt32("EmployeeID", id);
if(datestart == null)
{
var setdate = DateTime.Now;
datestart = setdate.AddMonths(-3).ToString();
}
if(dateend == null)
{
dateend = DateTime.Now.ToString();
}
var start = new SqlParameter("@StartDate", datestart);
var end = new SqlParameter("@EndDate", dateend);
var EmpId = new SqlParameter("@Id", id);
var tasks = LoadData("EXECUTE dbo.TaskView @StartDate, @EndDate,
@Id",start,end,EmpId);
ViewBag.start = DateTime.Parse(datestart);
ViewBag.end = DateTime.Parse(dateend);
return View(tasks);
}
接下來,我修改了瀏覽:
@model List<Dictionary<string, object>>
@{
ViewData["Title"] = "Employee Tasks";
}
<h2>Employee Tasks</h2>
<div class="panel panel-default">
<div class="panel-heading">Search by dates</div>
<div class="panel-body">
<form asp-controller="EmployeeTasks" asp-action="Index">
<label>Start Date</label>
<input type="date" name="datestart" id="start" [email protected]
/>
<label>End Date</label>
<input type="date" name="dateend" id="end" [email protected] />
<input type="submit" value="Search" />
</form>
</div>
</div>
<p>
<a asp-action="Create">Add New Employee Task</a>
</p>
@if (Model.FirstOrDefault() != null)
{
<table class="table table-bordered">
@foreach (var row in Model.FirstOrDefault())
{
<th>@row.Key</th>
}
@foreach (var row in Model)
{
<tr>
@foreach (var column in row)
{
<td>@column.Value</td>
}
</tr>
}
</table>
}
<div>
<a asp-controller="Employees" asp-action="Index">Back to Employee
Search</a>
</div>
最終的結果!
如果任何人有一個更簡單的方法,請張貼它作爲一個答案,所以我可以嘗試一下,不過這在.NET 1.1核心的偉大工程。
您的group by s對於列和body是不同的 - 意味着您不在同一個groupby上應該使用'EntryDate'的結果 – Jaya
@JS_GodBlessAll:將數字排成行中的日期,但是行應該是任務。我認爲這裏最大的問題在於,沒有真正的零或零作爲持有人,無法接受某些日期的任務。 我試着一個一個地構建行,但由於日期列是動態的,所以我無法建立一個能準確反映我需要捕獲的模型。 我也嘗試使用我發現[這裏]的SQL方法(http://stackoverflow.com/questions/34390090/whats-the-alternative-to-datatable-with-ado-net-under-mvc-6),但我似乎無法使其工作。 –