你意識到GroupBy
的結果是一個IGrouping<key, items>
對象的序列,不是嗎?每個組可能有不同數量的元素。這樣的序列不能轉換爲數據表。
根據MSDN System.Data.DataTableExtensions.CopyToDataTable<T>
通用參數T是DataRow
。我的編譯器抱怨你的GroupBy的結果不能爲CopyToDataTable輸入,因爲你的匿名類不是DataRow。
因此,我們必須將您未觸及的,已刪除和審覈的項目轉換爲一個有序序列,該序列可以轉換爲包含您要在表格中的數據的DataRows
。
我想在你的核心數據表中的項目至少有一個ID,並在審計數據表至少有一個AuditDate
的元素,一個CoreDataId
指審計項目的ID在覈心數據表(至少與項目存在一樣長)。
顯然你想把所有的數據放到一個表中,我假設你將這個數據放在一個對象中TableData
。
由於未觸及的項目不在AuditedData
的表格中,因此核心表格中未觸動的項目應具有TableData
。
所有已刪除的項目都不在覈心數據中,因此在AuditedData表中刪除的項目也需要有TableData
。
由於您要按日期時間訂購所有數據,您的TableData
還應包含一個審計日期。有些項目從未審計過,他們的AuditDate爲空。
待辦事項:決定如何對從未審計的項目進行排序?第一個或最後在有序的結果?*
class TableData
{
DateTime? AuditDate {get; set;} // used to order by date. null if never audited
...
}
class CoreData
{
public int Id {get; set;} // int may be any other type
public TableData {get; set;} // all untouched items should have this
// all others: choose what you want
...
}
class AuditData
{
public DateTime AuditDate {get; set;}
public int CoreId {get; set;}
public TableData {get; set;} // all deleted items should have this
// all others: choose what you want
...
}
IEnumerable<CoreData> coreData = ...
IEnumerable<AuditData> auditedData = ...
我想你能夠創建LINQ查詢轉換原來的核心數據和審計數據進入最後提到的序列。那些從未接觸過(從未被編輯過,也不能刪除)
項目
=是在coreData的所有項目,但不是在auditedData:
var auditedItemIds = auditedData
.Select(auditedItem => auditedItem.CoreId)
.Distinct();
IEnumerable<TableData> untouchedItems = coreData
.Where(coreItem => !auditedItemIds.Contains(coreItem.Id))
.Select(coreItem => coreItem.TableData;
已刪除郵件
=在auditedData
所有項目不在coreData
(已有) 我們只希望最近審計的數據項
var coreItemIds = coreData.Select(coreItem => coreItem.Id)
.Distinct();
IEnumerable<TableData> deletedItems = auditedData
// take only the audited items that are not in core data anymore:
.Where(auditedItem => !coreItemIds.Contains(auditedItem.CoreId)
// group the remaining items by same CoreId
.GroupdBy(
auditedItem => auditedItem.CoreId, // key of the group: coreId
autitedItem => auditedItem.TableData); // elements of the group
// from every group (= all audited items belonging to the same core item)
// take the element with the newest date
// = order by descending AuditDate and take FirstOrDefault
// because a group is created you are certain there is an element in the group
.Select(group => group
.OrderbyDescending(groupElement => groupElement.AuditDate)
.FirstOrDefault());
修改內容
=是在這兩個coreData
和auditedData
,我不知道,如果你從coreData
或auditedData
希望tableData
的所有項目。 LINQ查詢是相似的。
假設你想要的tableData
從最新審計:
var coreItemIds = coreData.Select(coreItem => coreItem.Id)
.Distinct();
IEnumerable<TableData> newestAuditData = auditedData
// take only auditedData that is still in coreData
.Where(auditedItem => coreItemIds.Contains(auditedItem.CoreId)
// group the remaining items by same CoreId
.GroupdBy(
auditedItem => auditedItem.CoreId, // key of the group: coreId
autitedItem => auditedItem.TableData); // elements of the group
// from every group (= all audited items belonging to the same core item)
// take the element with the newest date
// = order by descending AuditDate and take FirstOrDefault
// because a group is created you are certain there is an element in the group
.Select(group => group
.OrderbyDescending(groupElement => groupElement.AuditDate)
.FirstOrDefault());
你注意到Where
後的表達與刪除的項目相同,經審計的項目?
現在您只需確定如何對所有這些元素進行排序,然後將它們放入一個DataRows序列中即可。
IOrderedEnumerable<TableData> OrderQueryResult(
IEnumerable<TableData> unTouchedItems,
IEnumerable<TableData> deletedItems,
IEnumerable<TableData> auditedItems)
{
// TODO decide what order to use
return result;
}
class MyDataRow : DataRow
{
MyDataRow(TableData tableData)
{
// in the constructor, extract the data you want in the DataRow
}
}
IOrderedEnumerable<TableData> orderedTableData = OrderedQueryResult(
untouchedItems, deletedItems, newestAuditData);
IEnumerable<MyDataRow> dataRows = orderedTableData
.Select(tableData => new MyDataRow(tableData);
DataTable myTable = dataRows.CopyToDataTable();
最後,我不確定您的數據庫是否已經存在,或者您現在正在開發它。您的查詢非常困難,因爲您有兩個包含相同數據的表格:一個包含您的實際數據,另一個包含數據的歷史記錄。如果你有下面的表格,你的查詢將會容易得多
我用Entity-Framework格式寫這個。如果您使用任何其他方法,我相信您可以從中提取SQL表。
class CoreData
{
public int Id {get; set;}
public ... NeverChangingItems {get; set;}
public bool IsObsolete {get; set;}
// HistoricData is data that might change through history
public virtual ICollection<HistoricData> HistoricData {get; set;}
}
public class HistoricData
{
public int Id {get; set;}
public DateTime AuditDate {get; set;}
public ... ItemsThatChangeThroughoutHistory {get; set;}
// foreign key to owning Core
public int CoreDataId {get; set;}
public virtual CoreData CoreData {get; set;}
}
如果你有一個不變的核心數據表和一個歷史表,你的三個查詢將會簡單得多。此外,您不需要擁有未更改的核心數據的副本,因爲元素永遠不會被刪除。
請注意,在您使用的方法中,已刪除的項目實際上也未被刪除,因爲它們仍保留在已審覈的表格中。
欣賞你的時間哈羅德,週一將採取適當的態度 – Hank