AutoDetectChanges не работает, когда существует свойство навигации по списку - PullRequest
0 голосов
/ 22 июня 2019

Я столкнулся с ошибкой, когда в некотором коде, основанном на EF6, изменения не обнаруживаются (хотя они сохраняются в хранилище данных).

При использовании свойства навигации List<Child>изменения не обнаруживаются при изменении свойства в родительском объекте.EntityState остается неизменным.

Пример консольного приложения (.NET Framework 4.7.2 с NuGet EntityFramework 6.2) код:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;
using System.ComponentModel.DataAnnotations.Schema;

namespace EFStateTest
{
    public class Tests
    {
        public static void Main()
        {
            var context = new StandaloneContext();


            /* First time run, generate some test data to work with */
            if (!context.Set<ParentTable>().Any())
            {
                ParentTable p = new ParentTable()
                {
                    Data = "Foo",
                    Children = new List<ChildTable>()
                    {
                        new ChildTable()
                        {
                            ManyData = "Bar",
                        },
                    },
                };

                context.Set<ParentTable>().Add(p);
            }
            /* nth run, do the test */
            else
            {
                var p = context.Set<ParentTable>().FirstOrDefault();        // Get our test record

                p.Data = DateTime.Now.Ticks.ToString();     // Change some data

                try
                {
                    // Get the state
                    object d = p.GetType().GetField("_entityWrapper").GetValue(p);
                    System.Data.Entity.Core.Objects.ObjectStateEntry ose = d.GetType().GetProperty("ObjectStateEntry").GetValue(d) as System.Data.Entity.Core.Objects.ObjectStateEntry;
                    Console.WriteLine(ose.State);
                }
                catch
                {
                    Console.WriteLine("Not a proxy class");
                }
            }

            context.SaveChanges();
            Console.WriteLine("DONE");
            Console.ReadLine();
        }
    }

    // Context
    public class StandaloneContext : DbContext
    {
        public StandaloneContext() : base("Server=(local);Database=EFTest;Integrated Security=SSPI")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new ParentTableSchema());
            modelBuilder.Configurations.Add(new ChildTableSchema());

            base.OnModelCreating(modelBuilder);
        }
    }

    public class ParentTable
    {
        public virtual int Id { get; set; }
        public virtual string Data { get; set; }

        public virtual List<ChildTable> Children { get; set; }
    }

    public class ChildTable
    {
        public virtual int Id { get; set; }
        public virtual int ParentId { get; set; }
        public virtual string ManyData { get; set; }

        public virtual ParentTable Parent { get; set; }
    }

    public class ParentTableSchema : EntityTypeConfiguration<ParentTable>
    {
        public ParentTableSchema()
        {
            HasKey(m => m.Id)
                .Property(m => m.Id)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

            HasMany(m => m.Children)
                .WithRequired(c => c.Parent)
                .HasForeignKey(c => c.ParentId);
        }
    }

    public class ChildTableSchema : EntityTypeConfiguration<ChildTable>
    {
        public ChildTableSchema()
        {
            HasKey(m => m.Id)
                .Property(m => m.Id)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        }
    }
}

Запустите один раз, чтобы сгенерировать базу данных на локальном компьютере, иеще раз, чтобы показать ошибку.Изменение свойства родительского объекта (p.Data = DateTime.Now.Ticks.ToString();) не меняет отслеживаемое состояние объекта, я использую отражение, чтобы получить его здесь, но оно такое же, как при использовании ChangeTracker в контексте.

Теперь, если вы удалите коллекцию навигации для List<ChildTable> Children, то проблема исчезнет (но я вроде хочу свойство навигации), и средство отслеживания изменений правильно изменится на Изменено.

У меня уже естьисправить, но это не отвечает почему .Измените свойство навигации, чтобы оно было определено как ICollection<ChildTable> вместо List, IList и т. Д., И это также работает.

В документации, которую я до сих пор читал на EF, сказано, что в свойствах навигации необходимо реализовать ICollection - какой Listделает.Так что здесь дает?Я что-то не так делаю или что-то упускаю полностью?

...