2015-01-31 2 views
2

두 개의 엔터티로 분할 된 테이블 행을 삭제하려고합니다. 나는 주요 엔티티를 삭제하려고하면 내가 context.Entry(...).Reference를 사용하여 관련된 다른 개체를로드하지 전에 만약 내가 때여러 엔터티에서 분할 된 테이블 행을 삭제하는 중 오류가 발생했습니다.

, 나는

전에 관련 기관을 검색하기 위해 조금 바보입니다 .. 오류가 전체 행을 삭제 하시겠습니까? 내가 만난 context.Entry(...) 라인

잘못된 데이터를 주석 계속 경우

나는 다음과 같은 오류가 발생했습니다. 필요한 관계가 누락되었습니다. 상태 항목을 검토하여 제약 조건 위반의 출처를 확인하십시오.

다음 코드를 추가합니다. 누군가 이전에 관련 항목을 "로드"할 필요없이 분리 된 항목을 삭제하는 것을 도와 줄 수 있습니까?

using System.Data.Entity; 
using System.Linq; 

namespace Split 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     using (var context = new DataContext()) 
     { 
      var product = new Product() 
      { 
       Name = "my Article", 
       Photo = new ProductPhoto() { PhotoUrl = "http://myfoto.jpg" } 
      }; 

      context.Products.Add(product); 
      context.SaveChanges(); 
     } 

     using (var context = new DataContext()) 
     { 
      var product = context.Products.First(); 
      //context.Entry(product).Reference(e => e.Photo).Load(); 
      context.Products.Remove(product); 
      context.SaveChanges(); 
     } 
    } 
    } 

    class Product 
    { 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual ProductPhoto Photo { get; set; } 
    } 

    class ProductPhoto 
    { 
    public virtual int ProductId { 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<Product> Products { get; set; } 
    public DbSet<ProductPhoto> ProductPhotos { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Product>() 
      .ToTable("Products") 
      .HasKey(e => e.Id) 
      .HasRequired(e => e.Photo) 
      .WithRequiredPrincipal(e => e.Product); 

     modelBuilder.Entity<ProductPhoto>() 
      .ToTable("Products") 
      .HasKey(e => e.ProductId); 

     base.OnModelCreating(modelBuilder); 
    } 
    } 
} 

답변

0

은 아마도과 같이 제품을로드 :

var product = context.Products.Include(x => x.Photo).First(); 

이 줄을 저장 여전히 DB에서 사진을로드합니다.

0

계단식 삭제 규칙을 모델에 추가하십시오. 단지 id 값을 가지고 엔티티 객체 : 당신은 메모리에이 작업을 수행하는 as noted here.

3

가장 좋은 방법은 부양의 로딩을 방지하기 위해 데이터베이스에 해당 DELETE 규칙이 있어야하는 것은 스텁 개체을 사용하는 것입니다

var product = context.Products.First(); 
var photo = new ProductPhoto { ProductId = product.ProductId }; // Stub 
context.Entry(photo).State = System.Data.Entity.EntityState.Deleted; 
context.Products.Remove(product); 
context.SaveChanges(); 

당신은 Product의 이드 당신도 삭제할 수 있습니다 알고있는 경우 모두 두 스텁을 생성하여 ProductProductPhoto.

0

안녕 거트 아놀드 제안으로 해결하기 위해 경로 스텁 관련 하위 기관 에 대한 엔티티, 다른 하나는 내가 게시

을 (설명 참조) 작동으로 새 코드를 붙여 넣기 한 메모리에하는 것입니다 Gert Arnold가 제안한 아이디어가 담긴 솔루션은 아마도 코드를 최적화 할 수있을만큼 많이 만들었습니다.

엔티티에 동시성 토큰이 포함되어있는 경우 이러한 속성은 DELETE 문을 구성하는 데 사용되는 입니다. 스텁 엔티티 접근 방식을 계속 사용할 수 있지만 동시성 토큰 속성에 대한 값을 설정해야합니다.

인용구 : "Programming Entity Framework : DbContext Julia Lerman 및 Rowan Miller (O'Reilly). 저작권 2012 줄리아 러먼과 로완 밀러, 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<DataContext>()); 

      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<Product> Products { get; set; } 
     public DbSet<ProductInfo> ProductInfos { get; set; } 

     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      modelBuilder.Entity<Product>() // one-to-one 
       .ToTable("Products") 
       .HasKey(e => e.Id) 
       .HasRequired(e => e.Info) 
       .WithRequiredDependent(e => e.Product); 

      modelBuilder.Entity<ProductInfo>() // map to the same table Products 
       .ToTable("Products") 
       .HasKey(e => e.Id); 

      base.OnModelCreating(modelBuilder); 
     } 

    } 
} 
0

이 코드를 사용하여 재정의 메서드를 교체하고 확인

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
     modelBuilder.Entity<Product>() // one-to-one 
      .ToTable("Products") 
      .HasKey(e => e.Id) 
      .HasRequired(e => e.Info) 
      .WithRequiredDependent(e => e.Product); 

     modelBuilder.Entity<ProductInfo>() // map to the same table Products 
      .ToTable("Products") 
      .HasKey(e => e.Id); 

     //add this code 
     modelBuilder.Entity<Product>() 
      .HasRequired(p => p.Photo) // "Photo" defined in Product class for ProductPhoto class's object name 
      .WithRequiredPrincipal(c => c.Product);// "Product" defined in ProductPhoto class for Product's class object name 


      base.OnModelCreating(modelBuilder); 
} 
관련 문제