Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
30 changes: 29 additions & 1 deletion src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,11 @@ private string FormatCycle(
var (command1, command2, edges) = data[i];
Format(command1, builder);

switch (edges.First().Metadata)
var firstEdge = edges.FirstOrDefault();
Check.DebugAssert(
firstEdge is not null || (command1.Entries.Count == 0 && command2.Entries.Count == 0),
"Edge metadata may be null only when both commands have no entries, which occurs during predecessor traversal of migration data commands.");
Comment thread
AndriySvyryd marked this conversation as resolved.
Outdated
switch (firstEdge?.Metadata)
{
case IForeignKey foreignKey:
Format(foreignKey, command1, command2, builder);
Expand Down Expand Up @@ -432,6 +436,30 @@ private string FormatCycle(

private void Format(IReadOnlyModificationCommand command, StringBuilder builder)
{
if (command.Entries.Count == 0)
{
Check.DebugAssert(
command.Table is not null || command.StoreStoredProcedure is not null,
"Commands without entries must have table or stored procedure metadata because cycle errors need to identify the store object.");
Comment thread
AndriySvyryd marked this conversation as resolved.
Outdated

if (command.Schema == null)
{
builder.Append(command.TableName);
}
else
{
builder.Append(command.Schema);
builder.Append('.');
builder.Append(command.TableName);
}

builder.Append(' ');
builder.Append('[');
builder.Append(command.EntityState);
builder.Append(']');
return;
}

var entry = command.Entries.First();
var entityType = entry.EntityType;
builder.Append(entityType.DisplayName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1931,6 +1931,52 @@ public void Throws_on_conflicting_seed_data(bool enableSensitiveLogging)
_ => { },
enableSensitiveLogging: enableSensitiveLogging)).Message);

[Fact]
public void Throws_circular_dependency_instead_of_sequence_contains_no_elements_for_seed_data_cycle()
{
var exception = Assert.Throws<InvalidOperationException>(
() => Execute(
model =>
{
model.Entity(
"WorkflowType",
x =>
{
x.ToTable("WorkflowType");
x.Property<string>("Code").IsRequired();
x.Property<string>("FirstStepCode").IsRequired();
x.HasKey("Code");
});

model.Entity(
"WorkflowStep",
x =>
{
x.ToTable("WorkflowStep");
x.Property<string>("Code").IsRequired();
x.Property<string>("WorkflowTypeCode").IsRequired();
x.HasKey("Code");
});

model.Entity("WorkflowType").HasOne("WorkflowStep").WithMany().HasForeignKey("FirstStepCode");
model.Entity("WorkflowStep").HasOne("WorkflowType").WithMany("Steps").HasForeignKey("WorkflowTypeCode");
},
_ => { },
target =>
{
target.Entity("WorkflowType").HasData(
new { Code = "TEST", FirstStepCode = "TEST-01A" });

target.Entity("WorkflowStep").HasData(
new { Code = "TEST-01A", WorkflowTypeCode = "TEST" });
},
_ => { },
_ => { }));

Assert.DoesNotContain("Sequence contains no elements", exception.Message, StringComparison.Ordinal);
Assert.Contains("circular dependency", exception.Message, StringComparison.OrdinalIgnoreCase);
}

[Fact]
public void Add_column_with_order()
=> Execute(
Expand Down
Loading