Skip to content

Commit

Permalink
Fix for NullRef when adding graph with shadow keys
Browse files Browse the repository at this point in the history
Issue #4854

Switch to using Equals(x, y) instead of x.Equals(y).
  • Loading branch information
ajcvickers committed Apr 27, 2016
1 parent bc6ccba commit 46f5a83
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public bool Equals(object[] x, object[] y)

for (var i = 0; i < x.Length; i++)
{
if (!x[i].Equals(y[i]))
if (!Equals(x[i], y[i]))
{
return false;
}
Expand Down
94 changes: 94 additions & 0 deletions test/Microsoft.EntityFrameworkCore.Tests/DbContextTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5011,5 +5011,99 @@ public void Dispose()
}
}
}

[Fact]
public void Adding_entities_with_shadow_keys_should_not_throw()
{
using (var context = new NullShadowKeyContext())
{
var assembly = new TestAssembly { Name = "Assembly1" };
var testClass = new TestClass { Assembly = assembly, Name = "Class1" };
var test = context.Tests.Add(new Test { Class = testClass, Name = "Test1" }).Entity;

context.SaveChanges();

ValidateGraph(context, assembly, testClass, test);
}

using (var context = new NullShadowKeyContext())
{
var test = context.Tests.Single();
var assembly = context.Assemblies.Single();
var testClass = context.Classes.Single();

ValidateGraph(context, assembly, testClass, test);
}
}

private static void ValidateGraph(NullShadowKeyContext context, TestAssembly assembly, TestClass testClass, Test test)
{
Assert.Equal(EntityState.Unchanged, context.Entry(assembly).State);
Assert.Equal("Assembly1", assembly.Name);
Assert.Same(testClass, test.Class);

Assert.Equal(EntityState.Unchanged, context.Entry(testClass).State);
Assert.Equal("Class1", testClass.Name);
Assert.Equal("Assembly1", context.Entry(testClass).Property("AssemblyName").CurrentValue);
Assert.Same(test, testClass.Tests.Single());
Assert.Same(assembly, testClass.Assembly);

Assert.Equal(EntityState.Unchanged, context.Entry(test).State);
Assert.Equal("Test1", test.Name);
Assert.Equal("Assembly1", context.Entry(test).Property("AssemblyName").CurrentValue);
Assert.Equal("Class1", context.Entry(test).Property("ClassName").CurrentValue);
Assert.Same(testClass, assembly.Classes.Single());
}

private class TestAssembly
{
[System.ComponentModel.DataAnnotations.Key]
public string Name { get; set; }
public ICollection<TestClass> Classes { get; } = new List<TestClass>();
}

private class TestClass
{
public TestAssembly Assembly { get; set; }
public string Name { get; set; }
public ICollection<Test> Tests { get; } = new List<Test>();
}

private class Test
{
public TestClass Class { get; set; }
public string Name { get; set; }
}

private class NullShadowKeyContext : DbContext
{
public DbSet<TestAssembly> Assemblies { get; set; }
public DbSet<TestClass> Classes { get; set; }
public DbSet<Test> Tests { get; set; }

protected internal override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseInMemoryDatabase();

protected internal override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TestClass>(
x =>
{
x.Property<string>("AssemblyName");
x.HasKey("AssemblyName", nameof(TestClass.Name));
x.HasOne(c => c.Assembly).WithMany(a => a.Classes)
.HasForeignKey("AssemblyName");
});

modelBuilder.Entity<Test>(
x =>
{
x.Property<string>("AssemblyName");
x.HasKey("AssemblyName", "ClassName", nameof(Test.Name));
x.HasOne(t => t.Class).WithMany(c => c.Tests)
.HasForeignKey("AssemblyName", "ClassName");
});
}
}
}
}

0 comments on commit 46f5a83

Please sign in to comment.