dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.66k stars 3.15k forks source link

ChangeTracker :: ArgumentException when processing Include on a One to One self reference #1292

Closed maumar closed 9 years ago

maumar commented 9 years ago
    public class Accessory
    {
        public string Name { get; set; }
        public Accessory SynergyWith { get; set; }
        public string SynergyWithId { get; set; }
    }

    public class MyContext : DbContext
    {
        public DbSet<Weapon> Weapons { get; set; }
        public DbSet<Accessory> Accessories { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Weapon>().Property(typeof(int?), "ShadowKey");
            modelBuilder.Entity<Accessory>().Key(a => a.Name);
            modelBuilder.Entity<Accessory>().OneToOne(a => a.SynergyWith).ForeignKey<Accessory>(a => a.SynergyWithId).Required(false);
        }

        protected override void OnConfiguring(DbContextOptions options)
        {
            options.UseSqlServer(new SqlConnectionStringBuilder { DataSource = ".", InitialCatalog = "IncludeBash", IntegratedSecurity = true, MultipleActiveResultSets = true}.ToString());
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (var ctx = new MyContext())
            {
                ctx.Database.EnsureDeleted();
                ctx.Database.EnsureCreated();

                var scope = new Accessory
                {
                    Name = "Scope"
                };

                var lasersight = new Accessory
                {
                    Name = "Lasersight",
                    SynergyWith = scope,
                };

                var extendedClip = new Accessory
                {
                    Name = "Extended Clip",
                };

                ctx.Accessories.Add(scope, extendedClip, lasersight);

                ctx.SaveChanges();
            }

            using (var ctx = new MyContext())
            {
                var soldiers = ctx.Accessories.Include(a => a.SynergyWith).ToList();
                Console.WriteLine(  soldiers);
            }
        }
    }

throws:

Unhandled Exception: System.ArgumentNullException: Value cannot be null. Parameter name: keyValue at Microsoft.Data.Entity.Utilities.Check.NotNull[T](T value, String parameter Name) at Microsoft.Data.Entity.ChangeTracking.StateManager.TryGetEntry(EntityKey ke yValue) at Microsoft.Data.Entity.Query.QueryBuffer.GetEntity(IEntityType entityType, IValueReader valueReader, Boolean queryStateManager) at Microsoft.Data.Entity.Query.QueryBuffer.GetEntity(IEntityType entityType, IValueReader valueReader) at Microsoft.Data.Entity.Query.QueryBuffer.GetTargetEntity(IEntityType target EntityType, IValueReader valueReader, ICollection1 bufferedEntities) at Microsoft.Data.Entity.Query.QueryBuffer.<>c__DisplayClass0.<Include>b__1(I ValueReader valueReader) at System.Linq.Enumerable.WhereSelectArrayIterator2.MoveNext() at System.Linq.Enumerable.WhereEnumerableIterator1.MoveNext() at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at Microsoft.Data.Entity.Query.QueryBuffer.Include(Object entity, INavigation navigation, Func3 relatedValueReaders) at Microsoft.Data.Entity.Relational.Query.RelationalQueryModelVisitor._Includ eReference[TEntity](QueryContext queryContext, QuerySourceScope1 querySourceSco pe, INavigation navigation, DbDataReader dataReader, Int32 readerOffset) at lambda_method(Closure , DbDataReader ) at Microsoft.Data.Entity.Relational.Query.QueryingEnumerable1.Enumerator.Mov eNext() at System.Linq.Enumerable.<SelectManyIterator>d__142.MoveNext() at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext() at Microsoft.Data.Entity.Query.LinqOperatorProvider.<_TrackEntities>d__12.Mo veNext() at Microsoft.Data.Entity.Query.EntityQueryExecutor.EnumerableExceptionInterce ptor1.EnumeratorExceptionInterceptor.MoveNext() at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at IncludeBashing.Program.Main(String[] args) in D:\Projects\IncludeBashing\I ncludeBashing\Program.cs:line 287 Press any key to continue . . .

rowanmiller commented 9 years ago

Probably related to #1093

mikary commented 9 years ago

Traced the issue back to a null value returned by SimpleNullableEntityKeyFactory, asked @ajcvickers and he confirmed that this is a duplicate of #1093