我是在實現一個數據庫審計線索,從而CRUD操作通過我的控制器在我的Web API項目的執行將序列的新老POCO的和存儲他們的值,以後檢索(中間歷史,回滾等)。實體框架代碼優先和SQL Server 2012的序列
當我得到它的所有工作,我不喜歡它是如何使我的控制器在POST期間看起來,因爲我最後不得不打電話SaveChanges()
兩次,一次爲插入的實體獲取ID,然後再次提交審計記錄哪些需要知道該ID。
我設置了轉換項目(尚處於起步階段)使用序列來代替標識列。這還有進一步從SQL Server中抽象出來的好處,雖然這不是一個真正的問題,但它也允許我減少提交次數,並讓我從邏輯控制器中提取出邏輯並將其填充到我的服務層中從存儲庫中抽象出我的控制器,並讓我在這個「填充」層中執行審計工作。
一旦Sequence
對象的創建和存儲過程來揭露它,我創建了以下類:
public class SequentialIdProvider : ISequentialIdProvider
{
private readonly IService<SequenceValue> _sequenceValueService;
public SequentialIdProvider(IService<SequenceValue> sequenceValueService)
{
_sequenceValueService = sequenceValueService;
}
public int GetNextId()
{
var value = _sequenceValueService.SelectQuery("GetSequenceIds @numberOfIds", new SqlParameter("numberOfIds", SqlDbType.Int) { Value = 1 }).ToList();
if (value.First() == null)
{
throw new Exception("Unable to retrieve the next id's from the sequence.");
}
return value.First().FirstValue;
}
public IList<int> GetNextIds(int numberOfIds)
{
var values = _sequenceValueService.SelectQuery("GetSequenceIds @numberOfIds", new SqlParameter("numberOfIds", SqlDbType.Int) { Value = numberOfIds }).ToList();
if (values.First() == null)
{
throw new Exception("Unable to retrieve the next id's from the sequence.");
}
var list = new List<int>();
for (var i = values.First().FirstValue; i <= values.First().LastValue; i++)
{
list.Add(i);
}
return list;
}
}
它只是提供了兩種方式來獲得的ID,一個和範圍。
這在第一組單元測試中效果很好,但一旦我開始在真實世界的場景中測試它,我很快意識到一次調用GetNextId()
將返回相同的值,直到SaveChanges()
被調用,從而否定任何真正的好處。
我不確定是否有辦法創建第二個上下文(而不是選項)或去老式的ADO.NET並直接進行SQL調用並使用AutoMapper獲得相同的淨結果。這些都不吸引我,所以我希望別人有一個想法。
您的審計記錄是怎樣的?每桌一桌,一桌一桌?審覈中存儲了哪些信息?您審覈了哪些操作?你有通用的數據層嗎? – JotaBe
包含以下數據的單一審計表:包含舊數據或新數據的序列化POCO(或PUT情況下的兩者),受影響的表,該表中的記錄ID,更改的列的列表以及執行的操作生成審計(插入,刪除,更新)。 –
然後沒有辦法做到這一點。兩個SaveChanges選項看起來像唯一的解決方案。您不應該擔心兩件事,原因有兩個:1).NET使用連接池,2)EF不會逐批發送查詢,而是逐個發送查詢。所以使用兩個SaveChanges之間的差異應該可以忽略不計。唯一的其他選擇是使用GUID作爲PK:http://stackoverflow.com/questions/18200817/how-to-set-newid-for-guid-in-entity-framework但這增加了更多的缺點(糟糕的索引性能),因爲GUID太長。 – JotaBe