Skip to content

Commit cd5df15

Browse files
Merge branch 'master' into master
2 parents 3eedb83 + 730463b commit cd5df15

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1065
-875
lines changed

.github/ISSUE_TEMPLATE.md

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
### Description
2+
Describe the issue or proposed feature.
3+
4+
### Exception
5+
If you are seeing an exception, include the full exceptions details (message and stack trace).
6+
7+
```
8+
Exception message:
9+
Stack trace:
10+
```
11+
12+
### Fiddle or Project
13+
Create a Fiddle that reproduce the issue: https://dotnetfiddle.net/UC2JMc
14+
15+
Or provide a project/solution that we can run to reproduce the issue.
16+
- Make sure the project compile
17+
- Make sure to provide only the code that is required to reproduce the issue, not the whole project
18+
- You can send private code here: [email protected]
19+
20+
_Note: If you are not able to provide code we can run and that reproduce the issue, we will not be able to fix it either._
21+
22+
### Further technical details
23+
- EF version:
24+
- GraphDiff version:
25+
- Database Provider:

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
*.pfx
22
*.snk
33
Z.Lab/
4+
.vs/
45

56
# Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
67
[Bb]in/
@@ -110,3 +111,4 @@ Generated_Code #added for RIA/Silverlight projects
110111
_UpgradeReport_Files/
111112
Backup*/
112113
UpgradeLog*.XML
114+
GraphDiff/.vs/GraphDiff/v15/sqlite3/storage.ide
0 Bytes
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.1</TargetFramework>
5+
<AssemblyName>RefactorThis.GraphDiff</AssemblyName>
6+
<RootNamespace>RefactorThis.GraphDiff</RootNamespace>
7+
<Version>3.1.0</Version>
8+
<SignAssembly>true</SignAssembly>
9+
<AssemblyOriginatorKeyFile>zzzproject.pfx</AssemblyOriginatorKeyFile>
10+
</PropertyGroup>
11+
12+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
13+
<DocumentationFile>\GraphDiff.NetStandard21\RefactorThis.GraphDiff.xml</DocumentationFile>
14+
</PropertyGroup>
15+
16+
<ItemGroup>
17+
<PackageReference Include="EntityFramework" Version="6.3.0-preview7-19363-02" />
18+
</ItemGroup>
19+
20+
<Import Project="..\GraphDiff.Shared\GraphDiff.Shared.projitems" Label="Shared" />
21+
22+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* This code is provided as is with no warranty. If you find a bug please report it on github.
3+
* If you would like to use the code please leave this comment at the top of the page
4+
* License MIT (c) Brent McKendrick 2012
5+
*/
6+
7+
using System;
8+
using System.Data.Entity;
9+
using System.Linq.Expressions;
10+
using RefactorThis.GraphDiff.Internal;
11+
using RefactorThis.GraphDiff.Internal.Graph;
12+
13+
namespace RefactorThis.GraphDiff
14+
{
15+
public static class DbContextExtensions
16+
{
17+
/// <summary>
18+
/// Merges a graph of entities with the data store.
19+
/// </summary>
20+
/// <typeparam name="T">The type of the root entity</typeparam>
21+
/// <param name="context">The database context to attach / detach.</param>
22+
/// <param name="entity">The root entity.</param>
23+
/// <param name="mapping">The mapping configuration to define the bounds of the graph</param>
24+
/// <param name="allowDelete">Allow to delete from graph.</param>
25+
/// <returns>The attached entity graph</returns>
26+
public static T UpdateGraph<T>(this DbContext context, T entity,
27+
Expression<Func<IUpdateConfiguration<T>, object>> mapping = null, bool allowDelete = true)
28+
where T : class, new()
29+
{
30+
var root = mapping == null ? new GraphNode() : new ConfigurationVisitor<T>().GetNodes(mapping);
31+
root.AllowDelete = allowDelete;
32+
var graphDiffer = new GraphDiffer<T>(root);
33+
return graphDiffer.Merge(context, entity);
34+
}
35+
36+
/// <summary>
37+
/// Merges a graph of entities with the data store.
38+
/// </summary>
39+
/// <typeparam name="T">The type of the root entity</typeparam>
40+
/// <param name="context">The database context to attach / detach.</param>
41+
/// <param name="entity">The root entity.</param>
42+
/// <param name="allowDelete">Allow to delete from graph.</param>
43+
/// <returns>The attached entity graph</returns>
44+
public static T UpdateGraph<T>(this DbContext context, T entity, bool allowDelete)
45+
where T : class, new()
46+
{
47+
return context.UpdateGraph(entity, null, allowDelete);
48+
}
49+
50+
// TODO add IEnumerable<T> entities
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
5+
<HasSharedItems>true</HasSharedItems>
6+
<SharedGUID>c97b2c2c-b005-438b-8d0c-ee3557d03041</SharedGUID>
7+
</PropertyGroup>
8+
<PropertyGroup Label="Configuration">
9+
<Import_RootNamespace>GraphDiff.Shared</Import_RootNamespace>
10+
</PropertyGroup>
11+
<ItemGroup>
12+
<Compile Include="$(MSBuildThisFileDirectory)DbContextExtensions.cs" />
13+
<Compile Include="$(MSBuildThisFileDirectory)GraphDiffConfiguration.cs" />
14+
<Compile Include="$(MSBuildThisFileDirectory)Internal\ConfigurationVisitor.cs" />
15+
<Compile Include="$(MSBuildThisFileDirectory)Internal\DebugExtensions.cs" />
16+
<Compile Include="$(MSBuildThisFileDirectory)Internal\Extensions.cs" />
17+
<Compile Include="$(MSBuildThisFileDirectory)Internal\GraphDiffer.cs" />
18+
<Compile Include="$(MSBuildThisFileDirectory)Internal\Graph\AssociatedEntityGraphNode.cs" />
19+
<Compile Include="$(MSBuildThisFileDirectory)Internal\Graph\CollectionGraphNode.cs" />
20+
<Compile Include="$(MSBuildThisFileDirectory)Internal\Graph\GraphNode.cs" />
21+
<Compile Include="$(MSBuildThisFileDirectory)Internal\Graph\OwnedEntityGraphNode.cs" />
22+
<Compile Include="$(MSBuildThisFileDirectory)IUpdateConfiguration.cs" />
23+
</ItemGroup>
24+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup Label="Globals">
4+
<ProjectGuid>c97b2c2c-b005-438b-8d0c-ee3557d03041</ProjectGuid>
5+
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
6+
</PropertyGroup>
7+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
8+
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
9+
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
10+
<PropertyGroup />
11+
<Import Project="GraphDiff.Shared.projitems" Label="Shared" />
12+
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
13+
</Project>
Original file line numberDiff line numberDiff line change
@@ -1,110 +1,110 @@
1-
using System;
2-
using System.Linq.Expressions;
3-
using System.Reflection;
4-
using RefactorThis.GraphDiff.Internal.Graph;
5-
6-
namespace RefactorThis.GraphDiff.Internal
7-
{
8-
/// <summary>
9-
/// Reads an IUpdateConfiguration mapping and produces an GraphNode graph.
10-
/// </summary>
11-
/// <typeparam name="T"></typeparam>
12-
internal class ConfigurationVisitor<T> : ExpressionVisitor
13-
{
14-
private GraphNode _currentMember;
15-
private string _currentMethod = "";
16-
17-
public GraphNode GetNodes(Expression<Func<IUpdateConfiguration<T>, object>> expression)
18-
{
19-
var initialNode = new GraphNode();
20-
_currentMember = initialNode;
21-
Visit(expression);
22-
return initialNode;
23-
}
24-
25-
protected override Expression VisitMember(MemberExpression memberExpression)
26-
{
27-
var accessor = GetMemberAccessor(memberExpression);
28-
var newMember = CreateNewMember(accessor);
29-
30-
_currentMember.Members.Push(newMember);
31-
_currentMember = newMember;
32-
33-
return base.VisitMember(memberExpression);
34-
}
35-
36-
protected override Expression VisitMethodCall(MethodCallExpression expression)
37-
{
38-
_currentMethod = expression.Method.Name;
39-
40-
// go left to right in the subtree (ignore first argument for now)
41-
for (int i = 1; i < expression.Arguments.Count; i++)
42-
{
43-
Visit(expression.Arguments[i]);
44-
}
45-
46-
// go back up the tree and continue
47-
_currentMember = _currentMember.Parent;
48-
return Visit(expression.Arguments[0]);
49-
}
50-
51-
private GraphNode CreateNewMember(PropertyInfo accessor)
52-
{
53-
GraphNode newMember;
54-
switch (_currentMethod)
55-
{
56-
case "OwnedEntity":
57-
newMember = new OwnedEntityGraphNode(_currentMember, accessor);
58-
break;
59-
case "AssociatedEntity":
60-
newMember = new AssociatedEntityGraphNode(_currentMember, accessor);
61-
break;
62-
case "OwnedCollection":
63-
newMember = new CollectionGraphNode(_currentMember, accessor, true);
64-
break;
65-
case "AssociatedCollection":
66-
newMember = new CollectionGraphNode(_currentMember, accessor, false);
67-
break;
68-
default:
69-
throw new NotSupportedException("The method used in the update mapping is not supported");
70-
}
71-
return newMember;
72-
}
73-
74-
private static PropertyInfo GetMemberAccessor(MemberExpression memberExpression)
75-
{
76-
PropertyInfo accessor = null;
77-
var expression = memberExpression.Expression;
78-
var constantExpression = expression as ConstantExpression;
79-
80-
if (constantExpression != null)
81-
{
82-
var container = constantExpression.Value;
83-
var member = memberExpression.Member;
84-
85-
var fieldInfo = member as FieldInfo;
86-
if (fieldInfo != null)
87-
{
88-
dynamic value = fieldInfo.GetValue(container);
89-
accessor = (PropertyInfo) value.Body.Member;
90-
}
91-
92-
var info = member as PropertyInfo;
93-
if (info != null)
94-
{
95-
dynamic value = info.GetValue(container, null);
96-
accessor = (PropertyInfo) value.Body.Member;
97-
}
98-
}
99-
else
100-
{
101-
accessor = (PropertyInfo) memberExpression.Member;
102-
}
103-
104-
if (accessor == null)
105-
throw new NotSupportedException("Unknown accessor type found!");
106-
107-
return accessor;
108-
}
109-
}
1+
using System;
2+
using System.Linq.Expressions;
3+
using System.Reflection;
4+
using RefactorThis.GraphDiff.Internal.Graph;
5+
6+
namespace RefactorThis.GraphDiff.Internal
7+
{
8+
/// <summary>
9+
/// Reads an IUpdateConfiguration mapping and produces an GraphNode graph.
10+
/// </summary>
11+
/// <typeparam name="T"></typeparam>
12+
internal class ConfigurationVisitor<T> : ExpressionVisitor
13+
{
14+
private GraphNode _currentMember;
15+
private string _currentMethod = "";
16+
17+
public GraphNode GetNodes(Expression<Func<IUpdateConfiguration<T>, object>> expression)
18+
{
19+
var initialNode = new GraphNode();
20+
_currentMember = initialNode;
21+
Visit(expression);
22+
return initialNode;
23+
}
24+
25+
protected override Expression VisitMember(MemberExpression memberExpression)
26+
{
27+
var accessor = GetMemberAccessor(memberExpression);
28+
var newMember = CreateNewMember(accessor);
29+
30+
_currentMember.Members.Push(newMember);
31+
_currentMember = newMember;
32+
33+
return base.VisitMember(memberExpression);
34+
}
35+
36+
protected override Expression VisitMethodCall(MethodCallExpression expression)
37+
{
38+
_currentMethod = expression.Method.Name;
39+
40+
// go left to right in the subtree (ignore first argument for now)
41+
for (int i = 1; i < expression.Arguments.Count; i++)
42+
{
43+
Visit(expression.Arguments[i]);
44+
}
45+
46+
// go back up the tree and continue
47+
_currentMember = _currentMember.Parent;
48+
return Visit(expression.Arguments[0]);
49+
}
50+
51+
private GraphNode CreateNewMember(PropertyInfo accessor)
52+
{
53+
GraphNode newMember;
54+
switch (_currentMethod)
55+
{
56+
case "OwnedEntity":
57+
newMember = new OwnedEntityGraphNode(_currentMember, accessor);
58+
break;
59+
case "AssociatedEntity":
60+
newMember = new AssociatedEntityGraphNode(_currentMember, accessor);
61+
break;
62+
case "OwnedCollection":
63+
newMember = new CollectionGraphNode(_currentMember, accessor, true);
64+
break;
65+
case "AssociatedCollection":
66+
newMember = new CollectionGraphNode(_currentMember, accessor, false);
67+
break;
68+
default:
69+
throw new NotSupportedException("The method used in the update mapping is not supported");
70+
}
71+
return newMember;
72+
}
73+
74+
private static PropertyInfo GetMemberAccessor(MemberExpression memberExpression)
75+
{
76+
PropertyInfo accessor = null;
77+
var expression = memberExpression.Expression;
78+
var constantExpression = expression as ConstantExpression;
79+
80+
if (constantExpression != null)
81+
{
82+
var container = constantExpression.Value;
83+
var member = memberExpression.Member;
84+
85+
var fieldInfo = member as FieldInfo;
86+
if (fieldInfo != null)
87+
{
88+
dynamic value = fieldInfo.GetValue(container);
89+
accessor = (PropertyInfo) value.Body.Member;
90+
}
91+
92+
var info = member as PropertyInfo;
93+
if (info != null)
94+
{
95+
dynamic value = info.GetValue(container, null);
96+
accessor = (PropertyInfo) value.Body.Member;
97+
}
98+
}
99+
else
100+
{
101+
accessor = (PropertyInfo) memberExpression.Member;
102+
}
103+
104+
if (accessor == null)
105+
throw new NotSupportedException("Unknown accessor type found!");
106+
107+
return accessor;
108+
}
109+
}
110110
}

0 commit comments

Comments
 (0)