zzzprojects / GraphDiff

GraphDiff is a library that allows the automatic update of a detached graph using Entity Framework code first.
https://entityframework-graphdiff.net/overview
MIT License
333 stars 101 forks source link

Correct way of configuring "grand-children"? #63

Closed dsaf closed 10 years ago

dsaf commented 10 years ago

What is the correct way of configuring "grand-children"? Are they already supported? Every odd time I am updating the root object, GraphDiff deletes them.

My root business object:

public class Package
{
    public Package()
    {
        Applications = new List<Application>();
        ApplicationParts = new List<ApplicationPart>();
        Actions = new List<Action>();
        Reports = new List<Report>();
    }

    public List<ApplicationPart> ApplicationParts { get; set; }
    public List<Application> Applications { get; set; }
    public List<Action> Actions { get; set; }
    public List<Report> Reports { get; set; }
}

My update config:

uc => uc.OwnedCollection(p => p.Applications)
        .OwnedCollection(p => p.Applications, m => m.OwnedCollection(a => a.Actions))
        .OwnedCollection(p => p.Applications, m => m.OwnedCollection(a => a.Reports))
        .OwnedCollection(p => p.ApplicationParts)
        .OwnedCollection(p => p.Actions)
        .OwnedCollection(p => p.Reports);

Thank you.

ghost commented 10 years ago

Hi,

you don't map Applications.Applications.ApplicationParts while you do map Applications.ApplicationParts - maybe that's the problem?

If you do map a collection as owned, you ask GraphDiff to "synchronize" the contents of the database table with the collection (and its elements) within the object graph you passed to GraphDiff. So if that in-memory collection is empty (or doesn't contain all elements) GraphDiff will remove missing elements from the database as well.

To be more helpful we need more information: which grand-children are deleted and under what circumstances?

dsaf commented 10 years ago

Hi, thanks for prompt reply!

ApplicationParts do not have any children, so it's OK.

The scenario is the following: on pressing a button make a web request do de-serialize a Package and then save it to the database. Since de-serialization is involved a detached entity is created every time. The package is the same for testing. First request creates a package in DB from scratch, so GraphDiff is not involved. The second request will clear the grand-children (Package.Application.*), while I would expect it to be idempotent. I could see a bunch of delete statements when using SQL profiler. If I make the third request in a row, the grand-children are filled again.

dsaf commented 10 years ago

Also tried GraphDiffConfiguration.ReloadAssociatedEntitiesWhenAttached = true to no success.

dsaf commented 10 years ago

I changed the grand-children to associated collections (as it is more correct) but it did not help:

                       .OwnedCollection(p => p.Applications, m => m.AssociatedCollection(a => a.Actions))
                       .OwnedCollection(p => p.Applications, m => m.AssociatedCollection(a => a.Reports))
dsaf commented 10 years ago

Most representative domain objects (extra code removed):

public class Package
{
    public Guid Id { get; set; }

    public List<ApplicationPart> ApplicationParts { get; set; }
    public List<Application> Applications { get; set; }
    public List<Action> Actions { get; set; }
    public List<Report> Reports { get; set; }
}

public class Application
{
    public Guid PackageId { get; set; }

    public Guid Id { get; set; }

    public List<ApplicationAction> Actions { get; set; }
    public List<ApplicationReport> Reports { get; set; }
}

public class ApplicationAction : Action
{
    public Guid ApplicationId { get; set; }
}
dsaf commented 10 years ago

I am now trying to make Application* not inherit the Action or Report. Have different issue - will post separately. Not finished.

ghost commented 10 years ago

Hi,

from what you've posted so far I'm unable to guess what exactly is wrong, but if you create a Gist containing a minimal reproduction of your problem, I'm going debug it (and your other issue #68) to see if GraphDiff is responsible for these issues.

dsaf commented 10 years ago

Hi,

I came to a conclusion that specifying two parents simultaneously (PackageId and ApplicationId) is wrong conceptually. Consequently I have "denormalised" ApplicationAction and ApplicationReport so that they would no longer inherit Action and Report respectively.

While the technical problem is probably still there, my particular situation was resolved by changing my DB schema design.