Non vedo l'ora di estrarre le modifiche delta tonnellate di entità in DbContext e delegare l'effettivo impegno del DB al processo in background, ad esempio il lavoro Web di Azure.
Tentativo, ma non è stato possibile serializzare.
var deltaJson = "";
try
{
var modifiedEntries = _ctx.ChangeTracker
.Entries()
.Select(x => x.Entity)
.ToList();
deltaJson = JsonConvert.SerializeObject(modifiedEntries, Formatting.Indented);
}
La mia prossima speranza è quella di utilizzare nel database di memoria e possibilmente se potessimo serializzare l'intero oggetto grafico di DbContext.
È fattibile? Il tuo consiglio di esperti e qualsiasi suggerimento in questa direzione sarebbe molto utile.
EDIT: la mia versione:
public class DeltaTracking
{
public static List<T> Build<T>(ICollection<T> db, ICollection<T> req) where T : IR
{
return Build(db, req, new DT<T>());
}
public static List<T> Build<T>(ICollection<T> db, ICollection<T> req, IEqualityComparer<T> comp) where T : IStateTracking
{
db = db ?? new List<T>();
req = req ?? new List<T>();
List<T> added = req.Except(db, comp).ToList();
foreach (T a in added)
{
a.State = TrackingState.Added.ToString();
}
List<T> removed = db.Except(req, comp).ToList();
foreach (T r in removed)
{
r.State = TrackingState.Deleted.ToString();
}
List<T> unchanged = db.Intersect(req, comp).ToList();
foreach (T u in unchanged)
{
u.State = TrackingState.Unchanged.ToString();
}
List<T> resp = added.Union(removed, comp).Union(unchanged, comp).ToList();
return resp;
}
}
È possibile serializzare entità dal Change Tracker, tuttavia, dato che sembra che si desideri serializzare e scaricare un gran numero di modifiche, sarà probabilmente necessario impacchettare le modifiche in pagine più piccole, trasferirle sul filo, tracciare e comporre il set di modifiche sull'altro lato e assicurando che vengano riassemblati in ordine poiché il changeset si estenderà su entità correlate.
const int pageSize = 1000;
var count = context.ChangeTracker.Entries()
.Count(x => x.State == EntityState.Modified || x.State == EntityState.Added || x.State == EntityState.Deleted);
var pages = (int) Math.Ceiling((double) count / PageSize);
int loopCounter = 0;
while (loopCounter < pages)
{
var changes = context.ChangeTracker.Entries()
.Where(x => x.State == EntityState.Modified || x.State == EntityState.Added || x.State == EntityState.Deleted)
.Select(x => new { Type = x.Entity.GetType(), State = x.State.ToString(), Original = x.OriginalValues.ToObject(), Updated = x.CurrentValues.ToObject() })
.Skip(loopCounter * pageSize)
.Take(pageSize);
var data = new
{
PageNumber = loopCounter,
Changes = changes,
};
string changeData = JsonConvert.SerializeObject(data, Formatting.Indented);
// Fire across to destination to be processed. Be sure to send the total # of pages because the server cannot start processing these unless they are in order.
.Changes
conterrebbero lo stato del tipo (quali azioni intraprendere, aggiornare, aggiungere, eliminare) e i valori di entità originali e aggiornati applicabili.
Se si tratta solo di gestire gli aggiornamenti in batch, quindi escludere gli elementi Aggiungi / Elimina e lasciarli scorrere.
Dal lato del ricevitore non credo che sarà tanto semplice quanto prendere le entità modificate e collegarle a un DbContext per essere mantenute per gli aggiornamenti. Questi dovrebbero probabilmente essere caricati dalla destinazione DbContext e aggiornati in base ai campi nelle entità allegate. Ci sarebbe un po 'di lavoro per estrarre cose come PK per le operazioni di eliminazione. Le aggiunte dovrebbero essere piuttosto semplici.
L'altro test reale sarebbe la concorrenza tra il momento in cui vengono apportate le modifiche e quando saranno eseguite dal servizio in background. Si dovrebbe considerare di controllare il controllo delle versioni per eventuali aggiornamenti. Questo probabilmente non è una soluzione completa, ma si spera che dia qualche spunto o spunti di discussione.