Last active
April 4, 2018 09:43
-
-
Save synercoder/ca54951d01b75bf07a06c960405e5ec3 to your computer and use it in GitHub Desktop.
ManyToManyBug
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Microsoft Visual Studio Solution File, Format Version 12.00 | |
# Visual Studio 15 | |
VisualStudioVersion = 15.0.27004.2009 | |
MinimumVisualStudioVersion = 10.0.40219.1 | |
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManyToManyBug", "ManyToManyBug\ManyToManyBug.csproj", "{0660B97F-160A-4FC4-96FD-9F1BBDF086CE}" | |
EndProject | |
Global | |
GlobalSection(SolutionConfigurationPlatforms) = preSolution | |
Debug|Any CPU = Debug|Any CPU | |
Release|Any CPU = Release|Any CPU | |
EndGlobalSection | |
GlobalSection(ProjectConfigurationPlatforms) = postSolution | |
{0660B97F-160A-4FC4-96FD-9F1BBDF086CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |
{0660B97F-160A-4FC4-96FD-9F1BBDF086CE}.Debug|Any CPU.Build.0 = Debug|Any CPU | |
{0660B97F-160A-4FC4-96FD-9F1BBDF086CE}.Release|Any CPU.ActiveCfg = Release|Any CPU | |
{0660B97F-160A-4FC4-96FD-9F1BBDF086CE}.Release|Any CPU.Build.0 = Release|Any CPU | |
EndGlobalSection | |
GlobalSection(SolutionProperties) = preSolution | |
HideSolutionNode = FALSE | |
EndGlobalSection | |
GlobalSection(ExtensibilityGlobals) = postSolution | |
SolutionGuid = {64732E80-92CA-42F5-9447-C0E25ACC9816} | |
EndGlobalSection | |
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>netcoreapp2.0</TargetFramework> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.0-preview3-32116" /> | |
</ItemGroup> | |
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.EntityFrameworkCore; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace ManyToManyBug | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var optionsBuilder = new DbContextOptionsBuilder<ManyContext>(); | |
optionsBuilder.UseSqlServer("Server=localhost\\SQLEXPRESS;Database=ManyToManyTest;Trusted_Connection=True;MultipleActiveResultSets=true"); | |
// normal, is bugged | |
RecreateDatabase(optionsBuilder.Options); | |
FillFoosAndBars(optionsBuilder.Options); | |
AddSixManyToManyRelationsWithoutState(optionsBuilder.Options); | |
CheckSixRelations(optionsBuilder.Options); | |
// workaround | |
RecreateDatabase(optionsBuilder.Options); | |
FillFoosAndBars(optionsBuilder.Options); | |
AddSixManyToManyRelationsWithState(optionsBuilder.Options); | |
CheckSixRelations(optionsBuilder.Options); | |
Console.WriteLine("Done..."); | |
Console.ReadLine(); | |
} | |
static void RecreateDatabase(DbContextOptions<ManyContext> options) | |
{ | |
Console.WriteLine("Recreating database..."); | |
using (var context = new ManyContext(options)) | |
{ | |
context.Database.EnsureDeleted(); | |
context.Database.EnsureCreated(); | |
} | |
} | |
static void FillFoosAndBars(DbContextOptions<ManyContext> options) | |
{ | |
Console.WriteLine("Adding foos and bars..."); | |
using (var context = new ManyContext(options)) | |
{ | |
context.Foos.Add(new Foo() { FooName = "foo1" }); | |
context.Foos.Add(new Foo() { FooName = "foo2" }); | |
context.Foos.Add(new Foo() { FooName = "foo3" }); | |
context.Bars.Add(new Bar() { BarName = "bar1" }); | |
context.Bars.Add(new Bar() { BarName = "bar2" }); | |
context.Bars.Add(new Bar() { BarName = "bar3" }); | |
context.SaveChanges(); | |
} | |
} | |
static void AddSixManyToManyRelationsWithoutState(DbContextOptions<ManyContext> options) | |
{ | |
Console.WriteLine("Adding relationships using DbSet<>.Add"); | |
using (var context = new ManyContext(options)) | |
{ | |
var foo1 = context.Foos.Single(f => f.FooName == "foo1"); | |
var foo2 = context.Foos.Single(f => f.FooName == "foo2"); | |
var foo3 = context.Foos.Single(f => f.FooName == "foo3"); | |
var bar1 = context.Bars.Single(f => f.BarName == "bar1"); | |
var bar2 = context.Bars.Single(f => f.BarName == "bar2"); | |
var bar3 = context.Bars.Single(f => f.BarName == "bar3"); | |
context.FooBars.Add(new FooBar() { Foo = foo1, Bar = bar1 }); | |
context.FooBars.Add(new FooBar() { Foo = foo1, Bar = bar2 }); | |
context.FooBars.Add(new FooBar() { Foo = foo1, Bar = bar3 }); | |
context.FooBars.Add(new FooBar() { Foo = foo2, Bar = bar3 }); | |
context.FooBars.Add(new FooBar() { Foo = foo3, Bar = bar1 }); | |
context.FooBars.Add(new FooBar() { Foo = foo3, Bar = bar2 }); | |
context.SaveChanges(); | |
} | |
} | |
static void AddSixManyToManyRelationsWithState(DbContextOptions<ManyContext> options) | |
{ | |
Console.WriteLine("Adding relationships using DbSet<>.Add(...).State = EntityState.Added"); | |
using (var context = new ManyContext(options)) | |
{ | |
var foo1 = context.Foos.Single(f => f.FooName == "foo1"); | |
var foo2 = context.Foos.Single(f => f.FooName == "foo2"); | |
var foo3 = context.Foos.Single(f => f.FooName == "foo3"); | |
var bar1 = context.Bars.Single(f => f.BarName == "bar1"); | |
var bar2 = context.Bars.Single(f => f.BarName == "bar2"); | |
var bar3 = context.Bars.Single(f => f.BarName == "bar3"); | |
context.FooBars.Add(new FooBar() { Foo = foo1, Bar = bar1 }).State = EntityState.Added; | |
context.FooBars.Add(new FooBar() { Foo = foo1, Bar = bar2 }).State = EntityState.Added; | |
context.FooBars.Add(new FooBar() { Foo = foo1, Bar = bar3 }).State = EntityState.Added; | |
context.FooBars.Add(new FooBar() { Foo = foo2, Bar = bar3 }).State = EntityState.Added; | |
context.FooBars.Add(new FooBar() { Foo = foo3, Bar = bar1 }).State = EntityState.Added; | |
context.FooBars.Add(new FooBar() { Foo = foo3, Bar = bar2 }).State = EntityState.Added; | |
context.SaveChanges(); | |
} | |
} | |
static void CheckSixRelations(DbContextOptions<ManyContext> options) | |
{ | |
Console.WriteLine("Checking relationship count..."); | |
using (var context = new ManyContext(options)) | |
{ | |
var count = context.FooBars.Count(); | |
if(count != 6) | |
{ | |
Console.WriteLine("OMG OMG OMG!! BUG BUG BUG! FIRE AND BRIMSTONE!"); | |
Console.WriteLine($"Count is {count} instead of 6."); | |
} | |
else | |
{ | |
Console.WriteLine("Everything is as it should be."); | |
} | |
} | |
Console.WriteLine(); | |
} | |
} | |
public class ManyContext : DbContext | |
{ | |
public ManyContext(DbContextOptions<ManyContext> options) | |
: base(options) | |
{ } | |
public DbSet<Foo> Foos { get; set; } | |
public DbSet<Bar> Bars { get; set; } | |
public DbSet<FooBar> FooBars { get; set; } | |
protected override void OnModelCreating(ModelBuilder modelBuilder) | |
{ | |
// Key is a shadow property | |
modelBuilder.Entity<Foo>().Property(typeof(Guid), "Id").ValueGeneratedOnAdd(); | |
modelBuilder.Entity<Foo>().HasKey("Id"); | |
modelBuilder.Entity<Foo>().HasIndex(x => x.FooName).IsUnique(); | |
// Key is a shadow property | |
modelBuilder.Entity<Bar>().Property(typeof(Guid), "Id").ValueGeneratedOnAdd(); | |
modelBuilder.Entity<Bar>().HasKey("Id"); | |
modelBuilder.Entity<Bar>().HasIndex(x => x.BarName).IsUnique(); | |
// Keys are shadow properties | |
modelBuilder.Entity<FooBar>().Property(typeof(Guid), "Foo_Id"); | |
modelBuilder.Entity<FooBar>().HasOne(x => x.Foo).WithMany(x => x.FooBars).HasForeignKey("Foo_Id"); | |
modelBuilder.Entity<FooBar>().Property(typeof(Guid), "Bar_Id"); | |
modelBuilder.Entity<FooBar>().HasOne(x => x.Bar).WithMany(x => x.FooBars).HasForeignKey("Bar_Id"); | |
modelBuilder.Entity<FooBar>().HasKey("Foo_Id", "Bar_Id"); | |
} | |
} | |
public class FooBar | |
{ | |
public Foo Foo { get; set; } | |
public Bar Bar { get; set; } | |
} | |
public class Foo | |
{ | |
public string FooName { get; set; } | |
public ICollection<FooBar> FooBars { get; set; } | |
} | |
public class Bar | |
{ | |
public string BarName { get; set; } | |
public ICollection<FooBar> FooBars { get; set; } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<configuration> | |
<packageSources> | |
<add key="MyGetAspNetCore" value="https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json" /> | |
<add key="MyGetDotNetCore" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" /> | |
</packageSources> | |
</configuration> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment