diff --git a/GraphDiff/GraphDiff/DbContextExtensions.cs b/GraphDiff/GraphDiff/DbContextExtensions.cs index 4b10302..aa3c8ea 100644 --- a/GraphDiff/GraphDiff/DbContextExtensions.cs +++ b/GraphDiff/GraphDiff/DbContextExtensions.cs @@ -14,7 +14,34 @@ namespace RefactorThis.GraphDiff { public static class DbContextExtensions - { + { + /// + /// Merges a graph of entities with the data store. + /// + /// The type of the root entity + /// The database context to attach / detach. + /// The root entity. + /// /// The persisted entity, optional, for performance optimisation. + /// The mapping configuration to define the bounds of the graph + /// The attached entity graph + public static T UpdateGraph(this DbContext context, T entity, T persisted, Expression, object>> mapping) where T : class + { + return UpdateGraph(context, entity, persisted, mapping, null, null); + } + + /// + /// Merges a graph of entities with the data store. + /// + /// The type of the root entity + /// The database context to attach / detach. + /// The root entity. + /// The mapping configuration to define the bounds of the graph + /// The attached entity graph + public static T UpdateGraph(this DbContext context, T entity, Expression, object>> mapping) where T : class + { + return UpdateGraph(context, entity, null, mapping, null, null); + } + /// /// Merges a graph of entities with the data store. /// @@ -25,9 +52,9 @@ public static class DbContextExtensions /// Update configuration overrides /// The attached entity graph public static T UpdateGraph(this DbContext context, T entity, Expression, object>> mapping, UpdateParams updateParams = null) where T : class - { - return UpdateGraph(context, entity, mapping, null, updateParams); - } + { + return UpdateGraph(context, entity, null, mapping, null, updateParams); + } /// /// Merges a graph of entities with the data store. @@ -40,7 +67,7 @@ public static T UpdateGraph(this DbContext context, T entity, ExpressionThe attached entity graph public static T UpdateGraph(this DbContext context, T entity, string mappingScheme, UpdateParams updateParams = null) where T : class { - return UpdateGraph(context, entity, null, mappingScheme, updateParams); + return UpdateGraph(context, entity, null, null, mappingScheme, updateParams); } /// @@ -53,7 +80,7 @@ public static T UpdateGraph(this DbContext context, T entity, string mappingS /// The attached entity graph public static T UpdateGraph(this DbContext context, T entity, UpdateParams updateParams = null) where T : class { - return UpdateGraph(context, entity, null, null, updateParams); + return UpdateGraph(context, entity, null, null, null, updateParams); } /// @@ -80,7 +107,7 @@ public static T LoadAggregate(this DbContext context, Expression(this DbContext context, T entity, Expression, object>> mapping, + private static T UpdateGraph(this DbContext context, T entity, T persisted, Expression, object>> mapping, string mappingScheme, UpdateParams updateParams) where T : class { if (entity == null) @@ -94,28 +121,28 @@ private static T UpdateGraph(this DbContext context, T entity, Expression(context, queryLoader, entityManager, root); var queryMode = updateParams != null ? updateParams.QueryMode : QueryMode.SingleQuery; - return differ.Merge(entity, queryMode); + return differ.Merge(entity, persisted, queryMode); } private static GraphNode GetRootNode(Expression, object>> mapping, string mappingScheme, AggregateRegister register) where T : class - { - GraphNode root; - if (mapping != null) - { - // mapping configuration - root = register.GetEntityGraph(mapping); - } - else if (mappingScheme != null) - { - // names scheme - root = register.GetEntityGraph(mappingScheme); - } - else - { - // attributes or null - root = register.GetEntityGraph(); - } - return root; - } - } + { + GraphNode root; + if (mapping != null) + { + // mapping configuration + root = register.GetEntityGraph(mapping); + } + else if (mappingScheme != null) + { + // names scheme + root = register.GetEntityGraph(mappingScheme); + } + else + { + // attributes or null + root = register.GetEntityGraph(); + } + return root; + } + } } diff --git a/GraphDiff/GraphDiff/Internal/GraphDiffer.cs b/GraphDiff/GraphDiff/Internal/GraphDiffer.cs index e63ccfd..29dae9a 100644 --- a/GraphDiff/GraphDiff/Internal/GraphDiffer.cs +++ b/GraphDiff/GraphDiff/Internal/GraphDiffer.cs @@ -6,7 +6,7 @@ namespace RefactorThis.GraphDiff.Internal { internal interface IGraphDiffer where T : class { - T Merge(T updating, QueryMode queryMode = QueryMode.SingleQuery); + T Merge(T updating, T persisted, QueryMode queryMode = QueryMode.SingleQuery); } /// GraphDiff main entry point. @@ -26,7 +26,7 @@ public GraphDiffer(DbContext dbContext, IQueryLoader queryLoader, IEntityManager _entityManager = entityManager; } - public T Merge(T updating, QueryMode queryMode = QueryMode.SingleQuery) + public T Merge(T updating, T persisted, QueryMode queryMode = QueryMode.SingleQuery) { // todo query mode bool isAutoDetectEnabled = _dbContext.Configuration.AutoDetectChangesEnabled; @@ -37,7 +37,11 @@ public T Merge(T updating, QueryMode queryMode = QueryMode.SingleQuery) // Get our entity with all includes needed, or add a new entity var includeStrings = _root.GetIncludeStrings(_entityManager); - T persisted = _queryLoader.LoadEntity(updating, includeStrings, queryMode); + + if (persisted == null) + { + persisted = _queryLoader.LoadEntity(updating, includeStrings, queryMode); + } if (persisted == null) { @@ -52,7 +56,7 @@ public T Merge(T updating, QueryMode queryMode = QueryMode.SingleQuery) { throw new InvalidOperationException( String.Format("Entity of type '{0}' is already in an attached state. GraphDiff supports detached entities only at this time. Please try AsNoTracking() or detach your entites before calling the UpdateGraph method.", - typeof (T).FullName)); + typeof(T).FullName)); } // Perform recursive update