Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/Example1.BasicCRUD/DocumentationSnippets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ private static async Task QueryAsync(IGraph graph)
.Where(person => person.Department == "Engineering")
.ToListAsync();
// snippet-end: query
Console.WriteLine($"Found {engineers.Count} engineer(s).");
}

private static async Task UpdateAndDeleteAsync(IGraph graph, Person alice)
Expand Down
4 changes: 4 additions & 0 deletions examples/Example2.LINQAndTraversal/DocumentationSnippets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ private static async Task QueryRootsAsync(IGraph graph)
.Where(person => person.Age >= 28 && person.Age <= 32)
.ToListAsync();
// snippet-end: query-roots
Console.WriteLine($"Found {newYorkers.Count} New Yorker(s) and {ageRange.Count} person(s) in the age range.");
}

private static async Task TraverseAsync(IGraph graph)
Expand All @@ -32,6 +33,8 @@ private static async Task TraverseAsync(IGraph graph)
.Traverse<Knows, Person>(2)
.ToListAsync();
// snippet-end: traversal
Console.WriteLine(
$"Found {directConnections.Count} direct connection(s) and {twoHopConnections.Count} two-hop connection(s).");
}

private static async Task PathSegmentsAsync(IGraph graph)
Expand All @@ -42,5 +45,6 @@ private static async Task PathSegmentsAsync(IGraph graph)
.PathSegments<Person, Knows, Person>()
.ToListAsync();
// snippet-end: path-segments
Console.WriteLine($"Found {connections.Count} path segment(s).");
}
}
4 changes: 4 additions & 0 deletions examples/Playground/DocumentationSnippets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ private static async Task SetBasedMutationAsync(IGraph graph)
.Where(person => person.Email.EndsWith("@expired.example"))
.DeleteAsync(cascadeDelete: true);
// snippet-end: set-based-mutation
Console.WriteLine($"Updated {updated} and deleted {deleted} person(s).");
}

private static async Task Neo4jQuickStartAsync()
Expand All @@ -124,6 +125,7 @@ private static async Task Neo4jQuickStartAsync()
.OrderBy(u => u.CreatedDate)
.ToListAsync();
// snippet-end: neo4j-quick-start
Console.WriteLine($"Found {users.Count} active user(s).");
}

private static async Task AgeQuickStartAsync()
Expand All @@ -140,6 +142,7 @@ private static async Task AgeQuickStartAsync()
.Where(user => user.IsActive)
.ToListAsync();
// snippet-end: age-quick-start
Console.WriteLine($"Found {activeUsers.Count} active user(s).");
}

private static async Task InMemoryQuickStartAsync()
Expand All @@ -151,5 +154,6 @@ private static async Task InMemoryQuickStartAsync()
await graph.CreateNodeAsync(new Person { Name = "Alice" });
var alice = await graph.Nodes<Person>().Where(p => p.Name == "Alice").SingleAsync();
// snippet-end: in-memory-quick-start
Console.WriteLine(alice.Name);
}
}
27 changes: 15 additions & 12 deletions src/Graph.Age/Querying/Cypher/Execution/CypherEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ await DeleteNodesAsync(
}
else if (mutation.Kind == GraphMutationKind.Update)
{
var updateComplexPlan = complexPlan ?? throw new InvalidOperationException(
"An update mutation must have a complex-property plan.");
if (!constraintPlan.IsEmpty)
{
var rows = await ReadConstraintRowsAsync(
Expand All @@ -153,7 +155,7 @@ await ValidateUnselectedConstraintsAsync(
transaction,
cancellationToken).ConfigureAwait(false);
}
else if (complexPlan!.HasWork)
else if (updateComplexPlan.HasWork)
{
// Complex replacement spans multiple AGE statements. Lock every frozen parent in
// the same global order as constrained and entity-manager updates before any scalar
Expand All @@ -172,14 +174,14 @@ await transaction.Runner.AcquireElementLocksAsync(
_ = await ExecuteStatementAsync(statement, transaction, cancellationToken).ConfigureAwait(false);
}

if (complexPlan!.HasWork)
if (updateComplexPlan.HasWork)
{
await _complexPropertyManager.ReplaceGraphIdBoundComplexPropertiesAsync(
transaction.Runner,
nativeIdentities.Cast<long>().ToArray(),
complexPlan.RelationshipTypesToClear,
complexPlan.PropertyNamesToClear,
complexPlan.ReplacementEntity,
updateComplexPlan.RelationshipTypesToClear,
updateComplexPlan.PropertyNamesToClear,
updateComplexPlan.ReplacementEntity,
cancellationToken).ConfigureAwait(false);
}
}
Expand Down Expand Up @@ -232,14 +234,15 @@ await transaction.Runner.AcquireElementLocksAsync(
constraintPlan.Properties.Select(property => property.StorageName).ToArray(),
acquireWriteLock: false);
var records = await ExecuteStatementAsync(statement, transaction, cancellationToken).ConfigureAwait(false);
var rows = records.Select(record => new GraphMutationConstraintRow(
record["__nativeId"].As<long>(),
constraintPlan.Properties.Select((property, index) => new
var rows = records.Select(record =>
{
var values = constraintPlan.Properties.Select((property, index) =>
{
property.StorageName,
Value = (object?)record[CypherMutationPlanner.ConstraintValueColumn(index)].As<object>(),
})
.ToDictionary(item => item.StorageName, item => item.Value, StringComparer.Ordinal)))
object? value = record[CypherMutationPlanner.ConstraintValueColumn(index)].As<object>();
return new KeyValuePair<string, object?>(property.StorageName, value);
}).ToDictionary(item => item.Key, item => item.Value, StringComparer.Ordinal);
return new GraphMutationConstraintRow(record["__nativeId"].As<long>(), values);
})
.ToArray();
GraphMutationConstraintPlan.ValidateTargetRows(nativeIdentities, rows);
return rows;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ public async Task ConcurrentCollectionUpdates_SeparateTransactions_OneWriterItem
public async Task UpdateCleanup_RemovesOnlyComplexValue_DomainRelationshipAndNodeSurvive()
{
var cancellationToken = TestContext.Current.CancellationToken;
var (owner, domainNode, domainRelationship) = await SeedCollisionAsync(
var (owner, domainNode, _) = await SeedCollisionAsync(
complexCity: "Complex Seattle",
domainCity: "Domain Portland",
cancellationToken);
Expand Down
6 changes: 3 additions & 3 deletions src/Graph.CompatibilityTests/IQueryTraversalTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1656,8 +1656,8 @@ await Graph.ConnectAsync(
.OptionalTraverse<Knows, Person>()
.Select(result => new
{
SourceId = ((Person)result.Source).TestKey,
TargetId = result.Target == null ? null : ((Person)result.Target).TestKey,
SourceId = ((Person)result.Source).TestKey, // lgtm[cs/useless-cast-to-self]
TargetId = result.Target == null ? null : result.Target.TestKey,
})
.ToListAsync(TestContext.Current.CancellationToken);

Expand All @@ -1668,7 +1668,7 @@ await Graph.ConnectAsync(
Assert.Contains(results, result => ((Person)result.Source).TestKey == self.TestKey && ((Person?)result.Target)?.TestKey == self.TestKey);
Assert.Equal(
new[] { one.TestKey, many.TestKey }.Order().ToArray(),
incoming.Select(result => ((Person)result.Target!).TestKey).Order().ToArray());
incoming.Select(result => result.Target!.TestKey).Order().ToArray());
Assert.Equal(unmatched.TestKey, Assert.Single(projected).SourceId);
Assert.Null(projected[0].TargetId);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Graph.InMemory/Serialization/EntityReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public EntityInfo BuildEntityInfo(NodeRecord record, StoreState state, Type actu
elementType,
[.. children
.OrderBy(item => item.SequenceNumber)
.Select(item => (EntityInfo?)item.Item2)]);
.Select(item => item.Item2)]);
}

complexProperties[name] = new Property(
Expand Down
17 changes: 10 additions & 7 deletions src/Graph.Neo4j/Querying/Cypher/Execution/CypherEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,14 +214,17 @@ private async Task<IReadOnlyList<GraphMutationConstraintRow>> ReadConstraintRows
constraintPlan.Properties.Select(property => property.StorageName).ToArray(),
acquireWriteLock: true);
var records = await ExecuteStatementAsync(statement, transaction, cancellationToken).ConfigureAwait(false);
var rows = records.Select(record => new GraphMutationConstraintRow(
global::Neo4j.Driver.ValueExtensions.As<string>(record["__nativeId"]),
constraintPlan.Properties.Select((property, index) => new
var rows = records.Select(record =>
{
var values = constraintPlan.Properties.Select((property, index) =>
{
property.StorageName,
Value = (object?)record[CypherMutationPlanner.ConstraintValueColumn(index)],
})
.ToDictionary(item => item.StorageName, item => item.Value, StringComparer.Ordinal)))
object? value = record[CypherMutationPlanner.ConstraintValueColumn(index)];
return new KeyValuePair<string, object?>(property.StorageName, value);
}).ToDictionary(item => item.Key, item => item.Value, StringComparer.Ordinal);
return new GraphMutationConstraintRow(
global::Neo4j.Driver.ValueExtensions.As<string>(record["__nativeId"]),
values);
})
.ToArray();
GraphMutationConstraintPlan.ValidateTargetRows(nativeIdentities, rows);
return rows;
Expand Down
2 changes: 0 additions & 2 deletions src/Graph.Serialization.CodeGen/CodeGenModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -458,8 +458,6 @@ private static bool ImplementsGraphInterface(INamedTypeSymbol type, string inter

private static string FindPropertyNameForParameter(IParameterSymbol parameter)
{
var parameterName = parameter.Name;

return Utils.GetPropertyNameFromParameter(parameter);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ internal static IReadOnlyList<string> GetCompanionPropertyNames(string logicalNa
// deployed-storage compatibility promise: every newly persisted collection has metadata.
return new EntityCollection(
expectedElementType,
[.. storedEntities.OrderBy(item => item.SequenceNumber).Select(item => (EntityInfo?)item.Entity)]);
[.. storedEntities.OrderBy(item => item.SequenceNumber).Select(item => item.Entity)]);
}

if (expectedElementType != typeof(object) && metadata.ElementType != expectedElementType)
Expand Down
9 changes: 6 additions & 3 deletions tests/Graph.Core.Tests/GraphMutationModelBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -380,20 +380,23 @@ public void ConstraintPlan_RejectsCollectionConstraintBeforeSchemaAccess()
{
Expression<Func<InvalidCollectionConstraintMetadata, List<string>>> invalidSelector =
metadata => metadata.Values;
Expression<Func<GraphPropertySetters<Person>, GraphPropertySetters<Person>>> setters =
builder => builder.SetProperty(person => person.Nicknames, Array.Empty<string>());
var selection = GraphMutationModelBuilder.Build(UpdateCall(
Root<Person>(),
(Expression<Func<GraphPropertySetters<Person>, GraphPropertySetters<Person>>>)(builder =>
builder.SetProperty(person => person.Nicknames, Array.Empty<string>())))).Selection;
setters)).Selection;
var property = typeof(InvalidCollectionConstraintMetadata).GetProperty(
nameof(InvalidCollectionConstraintMetadata.Values))!;
var scalarProperty = typeof(InvalidCollectionConstraintMetadata).GetProperty(
nameof(InvalidCollectionConstraintMetadata.ScalarValue))!;
Expression<Func<InvalidCollectionConstraintMetadata, string>> scalarSelector =
metadata => metadata.ScalarValue;
var mutation = new GraphMutationModel(
GraphMutationKind.Update,
selection,
[
new GraphConstantPropertyAssignment(
(Expression<Func<InvalidCollectionConstraintMetadata, string>>)(metadata => metadata.ScalarValue),
scalarSelector,
scalarProperty,
nameof(InvalidCollectionConstraintMetadata.ScalarValue),
dynamic: false,
Expand Down
1 change: 1 addition & 0 deletions tests/Graph.Core.Tests/GraphQueryProviderBaseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ private static async Task ConsumeAsync<T>(IAsyncEnumerable<T> stream)
{
await foreach (var _ in stream)
{
// Enumerating the stream is the behavior under test.
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public Task Traverse_NoDepthOrDirection()
[Fact]
public Task Traverse_WidenedToINodeBeforeLabelFilter_LeavesStartUnconstrained()
{
var query = ((IGraphQueryable<INode>)Root.Nodes<Person>())
IGraphQueryable<INode> nodes = Root.Nodes<Person>();
var query = nodes
.OfLabel("Person")
.Traverse<Knows, Person>();

Expand Down Expand Up @@ -118,8 +119,8 @@ public Task OptionalTraverse_ComposesProjectionAndPaging()
.OptionalTraverse<Knows, Person>()
.Select(result => new
{
SourceKey = ((Person)result.Source).TestKey,
TargetKey = result.Target == null ? null : ((Person)result.Target).TestKey,
SourceKey = ((Person)result.Source).TestKey, // lgtm[cs/useless-cast-to-self]
TargetKey = result.Target == null ? null : result.Target.TestKey,
})
.Take(5);

Expand Down
Loading