Error deleting a table row splitted on multiple entities

前端 未结 6 998
耶瑟儿~
耶瑟儿~ 2021-01-06 05:18

I want to delete a table row that is split on two entities.

If I try to delete the main entity, I get an error if before I don\'t load the related other entity using

6条回答
  •  梦毁少年i
    2021-01-06 05:45

    Hi the path to solve as Gert Arnold suggest is to have in memory stubs one for the entity and another for related sub entities I had pasted a new code with that works (see comments)

    I posted the solution with the idea suggested by Gert Arnold, perhaps the code could be optimized, I tried to make it as much generic that I can.

    If your entity contains any concurrency tokens, these properties are also used to construct the DELETE statement. You can still use the stub entity approach, but you will need to set values for the concurrency token properties as well.

    Quoted from: “Programming Entity Framework: DbContext by Julia Lerman and Rowan Miller (O’Reilly). Copyright 2012 Julia Lerman and Rowan Miller, 978-1-449-31296-1.”

    using System;
    using System.Data.Entity;
    using System.Linq;
    using System.Reflection;
    
    namespace Split
    {
        class Program
        {
            static void Main()
            {
                Database.SetInitializer(new DropCreateDatabaseAlways());
    
                const int id = 1;
                const string split = "Info"; // contract: if the entity being delete has an Info property then the row has been splitted
    
                using (var context = new DataContext()) // Add
                {
                    var product = new Product 
                    {
                        Name = "my Article 1",
                        Info = new ProductInfo { PhotoUrl = "http://myphoto.jpg" } // when adding an entity the subEntity MUST BE included on the graph
                    };
    
                    context.Products.Add(product);
                    context.SaveChanges();
                }
    
                using (var context = new DataContext())
                {
                    var product = context.Products.Find(id);
                    context.Entry(product).Reference(e => e.Info).Load(); // when adding an entity the subEntity COULD BE OR NOT included on the graph, no need to include it if we are not going to modify it
    
                    product.Name = "MY ARTICULE 1";
                    product.Info.PhotoUrl = "HTTP://MYPHOTO.JPG";
                    context.Entry(product).State = EntityState.Modified;
                    context.SaveChanges();
                }
    
                using (var context = new DataContext())
                {
                    PropertyInfo propertyInfo;
    
                    context.Products.Find(id); // uncoment bring it to memory and test with entity in memory
    
                    var entity = context.Products.Local.FirstOrDefault(e => e.Id == id);
    
                    context.Entry(entity).Reference(e => e.Info).Load();
    
                    if (entity != null)                                      // there is a entity already yet in memory
                    {
                        propertyInfo = entity.GetType().GetProperty(split);  // contract
    
                        if (propertyInfo != null)
                        {
                            var subEntity = propertyInfo.GetValue(entity);         // get subEntity from entity Info property
                            context.Entry(subEntity).State = EntityState.Detached; // remove sub entity from ChangeTracker API
                            propertyInfo.SetValue(entity, null);                   // remove subEntity and relationship
                        }
    
                        context.Entry(entity).State = EntityState.Detached;  // remove entity from ChangeTracker API
                    }
    
                    entity = new Product { Id = id };                        // new entity stub
                    propertyInfo = entity.GetType().GetProperty(split);      // contract:
                    if (propertyInfo != null)
                    {
                        propertyInfo.SetValue(entity, null);                 // remove subEntity and and relationship
    
                        var subEntity = Activator.CreateInstance(propertyInfo.PropertyType); // create a new subEntity stub
                        subEntity.GetType().GetProperty("Id").SetValue(subEntity, id);       // set the foreinkey relation
                        context.Entry(subEntity).State = EntityState.Deleted;                // mark as deleted on context
                    }
    
                    context.Entry(entity).State = EntityState.Deleted;       // delete the entity
                    context.SaveChanges();
                }
            }
        }
    
        class Product
        {
            public virtual int Id { get; set; }
            public virtual string Name { get; set; }
    
            public virtual ProductInfo Info { get; set; }
        }
    
        class ProductInfo
        {
            public virtual int Id { get; set; }
            public virtual string PhotoUrl { get; set; }
            public virtual Product Product { get; set; }
        }
    
        class DataContext : DbContext
        {
            public DataContext()
                : base("name=DefaultConnection")
            {
                Configuration.ProxyCreationEnabled = false;
                Configuration.LazyLoadingEnabled = false;
    
    
            }
            public DbSet Products { get; set; }
            public DbSet ProductInfos { get; set; }
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Entity() // one-to-one
                    .ToTable("Products")
                    .HasKey(e => e.Id)
                    .HasRequired(e => e.Info)
                    .WithRequiredDependent(e => e.Product);
    
                modelBuilder.Entity() // map to the same table Products
                    .ToTable("Products")
                    .HasKey(e => e.Id);
    
                base.OnModelCreating(modelBuilder);
            }
    
        }
    }
    

提交回复
热议问题