Salakhetdinov Shamil
mcp2004 at mail.ru
Tue Apr 16 20:41:56 CDT 2013
Sample code part I: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data.Entity; using System.Linq; using System.Windows.Forms; namespace TestWindowsFormsApplication1 { public class GenericEntityGridViewHandler<C, T> : IDisposable where C : DbContext where T : class { private string _idFieldName; private string _altKeyFieldName; private string _dataLoadSql; public GenericEntityGridViewHandler( DataGridView entityDataGridView, BindingSource entityBindingSource, string dataLoadSql, string idFieldName = "Id", string altKeyFieldName = "Name") { _entityDataGridView = entityDataGridView; _entityBindingSource = entityBindingSource; _entityBindingSource.ListChanged += new ListChangedEventHandler(_entityBindingSource_ListChanged); _entityDataGridView.RowsRemoved += new DataGridViewRowsRemovedEventHandler(_entityDataGridView_RowsRemoved); _idFieldName = idFieldName; _altKeyFieldName = altKeyFieldName; _dataLoadSql = dataLoadSql; } private DataGridView _entityDataGridView; private BindingSource _entityBindingSource; private C _context; private IQueryable<T> _dataSource; private bool _loadInProgress; public void LoadData() { try { _loadInProgress = true; _context = (C)Activator.CreateInstance(typeof(C)); _dataSource = _context.Set(typeof(T)).SqlQuery(_dataLoadSql).OfType<T>().AsQueryable<T>(); _dataSource.Load(); _entityBindingSource.DataSource = _context.Set(typeof(T)).Local; _auditTrailItems = new Dictionary<string, AuditTrailItem>(); } finally { _loadInProgress = false; } } public class AuditTrailItem { public AuditTrailItem(System.Data.EntityState itemState, T item, string itemKey) { this.ItemState = itemState; this.Item = item; this.ItemKey = itemKey; } public System.Data.EntityState ItemState { get; private set; } public T Item { get; private set; } public string ItemKey { get; private set; } } // keeps individual data changes audit trail public Dictionary<string, AuditTrailItem> AuditTrailItems { get { return _auditTrailItems; } } private Dictionary<string, AuditTrailItem> _auditTrailItems; private void addAuditTrailItem(T item, System.Data.EntityState state, Dictionary<string, AuditTrailItem> auditTrailItems) { string key = getKeyValue(item); if (string.IsNullOrWhiteSpace(key)) return; key = string.Format("{0}:{1}", state, key); if (auditTrailItems.ContainsKey(key)) return; auditTrailItems.Add(key, new AuditTrailItem(state, item, key)); } private void auditTrailModelChanges(ref Dictionary<string, AuditTrailItem> auditTrailItems) { if (auditTrailItems == null) auditTrailItems = new Dictionary<string, AuditTrailItem>(); IEnumerable<T>[] checkStateSources = { (IEnumerable<T>)_context.Set(typeof(T)).Local, (IEnumerable<T>)_dataSource }; foreach (IEnumerable<T> checkStateSource in checkStateSources) { foreach (T item in checkStateSource) { switch (_context.Entry(item).State) { case System.Data.EntityState.Added: case System.Data.EntityState.Modified: case System.Data.EntityState.Deleted: addAuditTrailItem(item, _context.Entry(item).State, auditTrailItems); break; } } } } --- to be continued --- Среда, 17 апреля 2013, 5:39 +04:00 от Salakhetdinov Shamil <mcp2004 at mail.ru>: >Hi Scott -- > >Thank you for your sample. I have prepared mine, which I will post here in several subsequent posts as one posting limit is 20KB. > >By "individual changes" I mean *all* the data changes happened between data load and data saving, And I wanted to "capture" that individual data changes as soon as they happen not before .SaveChanges() call. <<< skipped >>> >