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 102 forks source link

Partially update owned collection #177

Closed Jogai closed 5 years ago

Jogai commented 6 years ago

I have a structure like this

+------------------+
| Grandparent      |
+------------------+
| Id               |
| SchemaCollection +---+
+------------------+   |
                       |
+------------------+   |
| Schema           |<--+
+------------------+
| Id               |
| VisitSchemas     +---+
+------------------+   |
                       |
+------------------+   |
| ChildrenSchemas  |<--+
+------------------+
| Id               |
| Child            |
| Schema           |
+------------------+

I'm saving this with:

        return myContext.UpdateGraph(grandParent,
            map => map
                .OwnedCollection(gp => gp.Schemas, s=> s.OwnedCollection(s => s.ChildrenSchemas))
        );

Wich works if everything is posted, but I want to partially update. Suppose we have in the database the following:

Grandparent; Id: 1

Schemas; Id: 1, {Data about 2013 in other properties} Id: 2, {Data about 2013 in other properties} Id: 3, {Data about 2014 in other properties} Id: 4, {Data about 2014 in other properties} Id: 5, {Data about 2015 in other properties} Id: 6, {Data about 2015 in other properties} Id: 7, {Data about 2016 in other properties} Id: 8, {Data about 2016 in other properties} Id: 9, {Data about 2017 in other properties} Id: 10, {Data about 2017 in other properties} Id: 11, {Data about 2018 in other properties} Id: 12, {Data about 2018 in other properties}

ChildrenSchemas: Id: 1, SchemaId: 1, ChildId: 1 Id: 2, SchemaId: 2, ChildId: 2 Id: 3, SchemaId: 3, ChildId: 3 Id: 4, SchemaId: 4, ChildId: 1 Id: 5, SchemaId: 5, ChildId: 2 Id: 6, SchemaId: 6, ChildId: 3 Id: 7, SchemaId: 7, ChildId: 1 Id: 8, SchemaId: 8, ChildId: 2 Id: 9, SchemaId: 9, ChildId: 3 Id: 10, SchemaId: 10, ChildId: 1 Id: 11, SchemaId: 11, ChildId: 2 Id: 12, SchemaId: 12, ChildId: 3

If I only load data of 2018, my update fails. How can I achieve only updating partial data (for example from 2018) in a childcollection of my main entity? Or when a new year started, there is no schema data yet, how should I save then?

JonathanMagnan commented 6 years ago

Hello @Jogai ,

Do you think you could provide a "working" project example/test with this issue?

It will help my developer investigate the issue more efficiently.

You can send it to: info@zzzprojects.com if you need to keep the source private

We now always ask for a sample project since most issues are either missing some essential information, have some syntax errors or are resolved by the requestor when creating it

Having a test project allows us to give faster support and a better experience to users of our free libraries.

Best Regards,

Jonathan


Performance Libraries context.BulkInsert(list, options => options.BatchSize = 1000); Entity Framework ExtensionsEntity Framework ClassicBulk OperationsDapper PlusLinqToSql Plus

Runtime Evaluation

Jogai commented 6 years ago

I've quickly thrown something together demonstrating the problem here: https://github.com/Jogai/Update.Partial.Collection

JonathanMagnan commented 6 years ago

Hello @Jogai ,

Thank you, we successfully reproduced this scenario with your example.

Is the problem caused because you want to attach item but doesn't want to removed current item if it doesn't exist?

For example, in your scenario there is a lot of delete that perharp you don't want:

exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=1
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=2
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=3
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=4
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=8
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=9
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=10
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=11
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=12
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=13
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=14
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=15
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=16
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=17
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=18
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=19
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=20
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=21
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=22
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=23
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=24
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=25
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=26
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=27
go
exec sp_executesql N'DELETE [dbo].[ChildSchemas]
WHERE ([Id] = @0)',N'@0 int',@0=28
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=1
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=2
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=3
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=4
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=8
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=9
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=10
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=11
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=12
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=13
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=14
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=15
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=16
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=17
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=18
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=19
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=20
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=21
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=22
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=23
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=24
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=25
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=26
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=27
go
exec sp_executesql N'DELETE [dbo].[Schemata]
WHERE ([Id] = @0)',N'@0 int',@0=28
go
Jogai commented 6 years ago

Yes, I want to update the graph that is loaded, but leave the items that are not loaded untouched.

JonathanMagnan commented 6 years ago

Thank we will look at it how to disable the "remove" logic.

Best Regards,

Jonathan

JonathanMagnan commented 5 years ago

Hello @Jogai ,

Sorry for the long delay,

The v3.0.2 has been released.

An overload has been added to allow to skip the Remove logic.

All you need to do is to pass the false parameter

return myContext.UpdateGraph(grandParent,
    map => map .OwnedCollection(gp => gp.Schemas, s=> s.OwnedCollection(s => s.ChildrenSchemas)),
    false
);

Let me know if everything works as expected.

Best Regards,

Jonathan

JonathanMagnan commented 5 years ago

Hello @Jogai ,

This issue will be closed since it has been resolved.

Feel free to reopen it if you feel otherwise.

Best Regards,

Jonathan

Jogai commented 5 years ago

Awesome! Works perfect. (Tested it now because I didnt have time to refactor my workaround earlier)

JonathanMagnan commented 5 years ago

Thank for letting us know ;) Don't worry, for the delay hehe