Updating EF objects based on deep JSON data

I have a data structure that looks something like this: foo 1:* bar 1:* baz

It might look something like this when passed to the client:

{
    id: 1,
    bar: [{
            id: 1,
            baz: []
        },
        {
            id: 2,
            baz: [{
                id: 1
            }]
        }
    ]
}

In my user interface, this is represented by a tree structure where the user can update / add / delete elements at all levels.

My question is when the user made the changes and I send the changed data to the server, how should I update the EF database? My initial thought was to do dirty tracking on the client side and use a dirty flag on the server to know what needs to be updated. Or maybe EF can be smart enough to do incremental updates?

+6
1

, EF .

, EF. , .

- ( ) , // . ( ) (-- (), -- (), -- ..), EF6 .

AFAIK - GraphDiff. :

using RefactorThis.GraphDiff;

IEnumerable<Foo> foos = ...;
using (var db = new YourDbContext())
{
    foreach (var foo in foos)
    {
        db.UpdateGraph(foo, fooMap =>
            fooMap.OwnedCollection(f => f.Bars, barMap =>
                barMap.OwnedCollection(b => b.Bazs)));
    }
    db.SaveChanges();
}

. GraphDiff Entity Framework - .

, , EF Core , EF6 ( EF Core , , t ).

- . , UpdateGraph , , :

db.Configuration.AutoDetectChangesEnabled = false;
var fooIds = foos.Where(f => f.Id != 0).Select(f => f.Id).ToList();
var oldFoos = db.Foos
    .Where(f => fooIds.Contains(f.Id))
    .Include(f => f.Bars.Select(b => b.Bazs))
    .ToDictionary(f => f.Id);
foreach (var foo in foos)
{
    Foo dbFoo;
    if (!oldFoos.TryGetValue(foo.Id, out dbFoo))
    {
        dbFoo = db.Foos.Create();
        dbFoo.Bars = new List<Bar>();
        db.Foos.Add(dbFoo);
    }
    db.Entry(dbFoo).CurrentValues.SetValues(foo);
    var oldBars = dbFoo.Bars.ToDictionary(b => b.Id);
    foreach (var bar in foo.Bars)
    {
        Bar dbBar;
        if (!oldBars.TryGetValue(bar.Id, out dbBar))
        {
            dbBar = db.Bars.Create();
            dbBar.Bazs = new List<Baz>();
            db.Bars.Add(dbBar);
            dbFoo.Bars.Add(dbBar);
        }
        else
        {
            oldBars.Remove(bar.Id);
        }
        db.Entry(dbBar).CurrentValues.SetValues(bar);
        var oldBazs = dbBar.Bazs.ToDictionary(b => b.Id);
        foreach (var baz in bar.Bazs)
        {
            Baz dbBaz;
            if (!oldBazs.TryGetValue(baz.Id, out dbBaz))
            {
                dbBaz = db.Bazs.Create();
                db.Bazs.Add(dbBaz);
                dbBar.Bazs.Add(dbBaz);
            }
            else
            {
                oldBazs.Remove(baz.Id);
            }
            db.Entry(dbBaz).CurrentValues.SetValues(baz);
        }
        db.Bazs.RemoveRange(oldBazs.Values);
    }
    db.Bars.RemoveRange(oldBars.Values);
}
db.Configuration.AutoDetectChangesEnabled = true;
+5

All Articles