मेरे पास कई से कई तालिकाएं हैं जो संदर्भ देती हैं। अपने आप में यह पागल लगता है इसलिए समस्या के बेहतर दृश्य के लिए यहां एक छवि है 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);
        }
    }

कुछ पता है कि ऐसा क्यों हो रहा है? क्या इसे my . के साथ कुछ करना है

संबंध या? पीएस (उदाहरण foos के साथ सरलीकृत है :))

1
john 5 सितंबर 2018, 21:47

1 उत्तर

सबसे बढ़िया उत्तर

मेरा मानना ​​है कि समस्या मैपिंग 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); भी सेट किया है। वे दोनों एक और एक ही का प्रतिनिधित्व करते हैं, इसलिए जब आप ऐड को कॉल करते हैं, तो ईएफ कोर फिक्सअप for.Id के लिए नया गाइड बनाता है और इसे dependencyFoo.DependentOfId को असाइन करता है। उसी समय, dependencyFoo.Dependent null रहता है और चूंकि dependencyFoo.DependentId का मान Guid.Empty है, EF Core इसे एक नया गाइड बनाता है और असाइन करता है।

समस्या को ठीक करने के लिए, बस धाराप्रवाह मानचित्रण में संग्रहों का आदान-प्रदान करें:

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);
1
Ivan Stoev 5 सितंबर 2018, 22:41
क्या यह डॉक्स में कहीं लिखा है? मुझे सेल्फ रेफरेंसिंग टेबल के लिए कई दस्तावेज़/लेख नहीं मिल रहे हैं, पीएस: मुझे माइग्रेशन करने की ज़रूरत नहीं थी, ऐसा क्यों है?
 – 
john
5 सितंबर 2018, 23:28
नहीं। लेकिन यह तार्किक है। मान लें कि आपके पास Person Children और Parents संग्रह, और PersonLink Parent और Child संदर्भों के साथ हैं। फिर संबंध हैं Person.Children <-> PersonLink.Parent और Person.Parents <-> PersonLink.Child
 – 
Ivan Stoev
6 सितंबर 2018, 01:11
आपको माइग्रेशन की आवश्यकता नहीं है क्योंकि संग्रह नेविगेशन गुणों का आदान-प्रदान करने से लिंक तालिका FK नहीं बदलती है।
 – 
Ivan Stoev
6 सितंबर 2018, 01:12