Таблица ссылок "многие ко многим" - идентификатор guid меняет сам себя - PullRequest
0 голосов
/ 05 сентября 2018

У меня есть много-много таблиц, на которые ссылается Само по себе это звучит безумно, так что вот изображение для лучшего понимания проблемы https://i.stack.imgur.com/lj2zZ.png

Я использую направляющие как первичные и внешние ключи. Когда я пытаюсь добавить новый экземпляр Foo в базу данных, который имеет отношение к некоторому foo из базы данных, и в тот самый момент, когда строка myDbContext.Set<Foo>().Add(foo); пройдена, Guid https://i.stack.imgur.com/WlFW9.png изменяется до https://i.stack.imgur.com/989nb.png

Код для создания базы данных:

 internal class Foo
    {
        public Guid Id { get; set; }
        public string Title { get; set; }

        public virtual List<DependencyFoo> Dependents { get; set; }
        public virtual List<DependencyFoo> DependentsOf { get; set; }
    }

   internal class DependencyFoo
    {
        public virtual Foo Dependent { get; set; }
        public Guid DependentId { get; set; }

        public virtual Foo DependentOf { get; set; }
        public Guid DependentOfId { get; set; }
    }

internal class MyDbContext : DbContext
    {
        public DbSet<Foo> Foos { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Data Source=.\\SQLEXPRESS;Initial Catalog=fooDb;Trusted_Connection=True;Integrated Security=True");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<DependencyFoo>()
              .HasKey(x => new { x.DependentOfId, x.DependentId });

            modelBuilder.Entity<DependencyFoo>()
                .HasOne(x => x.DependentOf)
                .WithMany(x => x.DependentsOf)
                .HasForeignKey(x => x.DependentOfId)
                .OnDelete(DeleteBehavior.Restrict);

            modelBuilder.Entity<DependencyFoo>()
                .HasOne(x => x.Dependent)
                .WithMany(x => x.Dependents)
                .HasForeignKey(x => x.DependentId);
        }
    }

Фактическое тестирование:

internal class Program
    {
        private static void Main(string[] args)
        {
            MyDbContext myDbContext = new MyDbContext();
            myDbContext.Set<Foo>().Add(new Foo { Title = "Some cool title" });
            myDbContext.SaveChanges();

            Foo fooDb = myDbContext.Set<Foo>().FirstOrDefault(x => x.Title == "Some cool title");
            DependencyFoo dependencyFoo = new DependencyFoo
            {
                DependentOfId = fooDb.Id
            };

            Foo foo = new Foo
            {
                DependentsOf = new List<DependencyFoo>()
            };
            foo.DependentsOf.Add(dependencyFoo);

            myDbContext.Set<Foo>().Add(foo);
        }
    }

Есть идеи, почему это происходит? Это как-то связано с моим

отношения или? PS (пример упрощен с помощью foos:))

1 Ответ

0 голосов
/ 05 сентября 2018

Я считаю, что проблема с отображениями Foo.Dependents <-> DependencyFoo.Dependent и Foo.DependentsOf <-> DependencyFoo.DependentOf.

Фактические иждивенцы / иждивенцы foo должны действительно быть что-то вроде (псевдокод):

IEnumerable<Foo> fooDependents = db.Set<DependencyFoo>()
    .Where(d => d.DependentOf.Id == foo.Id)
    .Select(d => d.Dependent);

IEnumerable<Foo> fooDependentsOf = db.Set<DependencyFoo>()
    .Where(d => d.Dependent.Id == foo.Id)
    .Select(d => d.DependentOf);

Обратите внимание, как происходит обмен ролями коллекций в основном объекте и ссылочных навигационных свойствах в объекте ссылки. Чтобы получить зависимых , необходимо выбрать связанный зависимый , отфильтрованный по зависимому из . И наоборот.

В настоящее время вы установили dependencyFoo.DependentOfId = fooDb.Id, а также foo.DependentsOf.Add(dependencyFoo);. Оба они представляют одно и то же, поэтому, когда вы вызываете add, исправление EF Core генерирует новый Guid для for.Id и присваивает его dependencyFoo.DependentOfId. В то же время, dependencyFoo.Dependent остается null, и поскольку значение dependencyFoo.DependentId равно Guid.Empty, EF Core создает и назначает ему новый Guid.

Чтобы устранить проблему, просто поменяйте коллекции в беглом отображении:

modelBuilder.Entity<DependencyFoo>()
    .HasOne(x => x.DependentOf)
    .WithMany(x => x.Dependents)
    .HasForeignKey(x => x.DependentOfId)
    .OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<DependencyFoo>()
    .HasOne(x => x.Dependent)
    .WithMany(x => x.DependentsOf)
    .HasForeignKey(x => x.DependentId);

или альтернативно (эффект тот же, мне просто легче читать и следовать):

modelBuilder.Entity<Foo>()
    .HasMany(x => x.Dependents)
    .WithOne(x => x.DependentOf)
    .HasForeignKey(x => x.DependentOfId)
    .OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<Foo>()
    .HasMany(x => x.DependentsOf)
    .WithOne(x => x.Dependent)
    .HasForeignKey(x => x.DependentId);
...