Giter VIP home page Giter VIP logo

reconciler's Introduction

Graph Reconciler for Entity Framework 6 and Core

Build status

Warning: This library is unmaintained. I was motivated to create this initial effort, but I want to be upfront with any potential user that I won't develop it any further.

Teaser

This library allows you to write

    await context.ReconcileAsync(personSentFromClient, e => e
        .WithOne(p => p.Address)
        .WithMany(p => p.Tags, e2 => e2
            .WithShared(p => p.Tag))
        ;
    await context.SaveChangesAsync();

and it will sync the four respective tables to match the given, detached personSentFromClient entity by adding, updating and removing entities as required.

Its primary use case are updates on multiple related entities retrieved from a client through an API.

It is a replacement for the GraphDiff library.

The EF 6 and EF Core versions share the same source code as far as possible to ensure consistency.

NuGet

There is one NuGet package for each of the two frameworks:

Install-Package Reconciler.Ef6
Install-Package Reconciler.EfCore

The EF6 version also has a prerelease package that targets netstandard2.1 and EF6.3 for use with .NET Core.

Definitions

  • Template entities are the entities to reconcile towards (personSentFromClient in the teaser sample)
  • The extent is the extent of the subtree rooted in the template entity of the first parameter that is to be reconciled as defined by the second parameter to the Reconcile extension methods.

Further features

The extent definition can also contain certain extra information to help with common scenarios that would otherwise often require some convoluted manual code.

Fixing

Sometimes we need to employ certain fixes on nested parts of the graph on saving:

.OnInsertion(e => e.Id == Guid.NewGuid())
.OnInsertion(e => e.CreatedAt == DateTimeOffset.Now)
.OnUpdate(e => e.ModifiedAt == DateTimeOffset.Now)

The OnUpdate definitions apply to insertions as well.

Note the use of the equality operator, as the assignment operator can't be used in expression trees in C#. Also note that the insertion definitions prevent modifications on updates - you don't have to worry about modified CreatedAt values being persisted to storage.

Exclude properties

Sometimes some properties should not be updated, and sometimes they shouldn't even be passed to a client on loading:

.WithReadOnly(e => e.Unmodifiable)
.WithBlacked(e => e.Secret)

Some details and caveats

The are some things to be aware of:

  • I'm using the library in production, but that doesn't mean it's mature. The test suite is thin and you may hit issues.
  • I don't use database-generated keys in my own applications (I prefer application-generated uuids over database-generated integer sequences). Reconciler has not been tested with database-generated keys and there may be issues.
  • Specifying relationships on derived classes in models with inheritance is not supported.
  • Using entities that are part of an inheritance hierarchy in all other contexts is also untested and likely doesn't work yet.
  • Many-to-many relationships are not supported and will probably never be.
  • The foreign key properties in the template entity must be set to match the respective navigational properties before the call to one of the Reconcile overloads is made. For example, it should be that person.AddressId == person.Address.Id in the unit test's sample model.
  • The extent must represent a subtree, i.e. have no cycles, and all entities must appear only once.
  • The Reconcile overloads themselves access the database only for reading and thus need to be followed by a SaveChanges call.
  • The number of reads done is the number of entities either in storage or in the template that are covered by the extent and have a non-trivial sub-extent themselves. In the above example, the address would have been fetched with the person itself and cause no further load, but there would be one load per tag-to-person bridge table row which each include the respective tag. There's room for optimization here, but that's where it's at.

GraphDiff

Before writing this replacement I used the GraphDiff library, but since it is no longer maintained I became motivated to write my own solution. In particular, I wanted

  • Entity Framework Core support,
  • async/await support and
  • really understand what's going on.

As I don't fully understand the original there are some differences beyond the names of functions: GraphDiff had OwnedEntity, OwnedCollection and AssociatedCollection as options for how to define the extent, and I don't quite know what the difference between associated and owned is.

Reconciler has WithOne, WithMany and WithShared:

WithOne and WithMany reconcile a scalar or collection navigational property, respectively, through respective addition, update and removal operations. WithShared only works on scalar navigational properties and doesn't remove a formerly related entity that is now no longer related. This is useful, for example, in the sample in the teaser where we want to insert new tag entities when they are needed but don't want to remove them as they may be shared by other entities.

Roadmap

There are a number of exciting features that would make this library much more useful. See this document for further information.

reconciler's People

Contributors

jtheisen avatar miriamblumenstein avatar sheva-serga avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.