2014-03-29 3 views
0

나는 뭔가를하려고하는데, 여기에 "데모"이라는 매우 간단한 예가 있습니다. (이 데모는 아무 의미가 없지만 내가 할 노력하고있어 일반적인 아이디어 제공)엔티티 프레임 워크 6.1 첨부되지 않은 경우 확인 후 충돌을 첨부하십시오

은 내가

새로운 컨텍스트를 생성하지 않고 할 수있는 방법이

을 시도 것을 주석을?

이 데이터베이스는 SQL 서버에 처음

C# 코드

SQL 스크립트가

USE [testing] 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[LookupTable](
    [LookupId] [int] NOT NULL, 
CONSTRAINT [PK_LookupTable] PRIMARY KEY CLUSTERED 
(
    [LookupId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[MainTable](
    [MainId] [int] NOT NULL, 
CONSTRAINT [PK_MainTable] PRIMARY KEY CLUSTERED 
(
    [MainId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[MainTable_LookupTable](
    [MainId] [int] NOT NULL, 
    [LookupId] [int] NOT NULL, 
CONSTRAINT [PK_MainTable_LookupTable] PRIMARY KEY CLUSTERED 
(
    [MainId] ASC, 
    [LookupId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 
INSERT [dbo].[LookupTable] ([LookupId]) VALUES (1) 
GO 
INSERT [dbo].[MainTable] ([MainId]) VALUES (10) 
GO 
INSERT [dbo].[MainTable_LookupTable] ([MainId], [LookupId]) VALUES (10, 1) 
GO 
ALTER TABLE [dbo].[MainTable_LookupTable] WITH CHECK ADD CONSTRAINT [FK_MainTable_LookupTable_LookupTable] FOREIGN KEY([LookupId]) 
REFERENCES [dbo].[LookupTable] ([LookupId]) 
GO 
ALTER TABLE [dbo].[MainTable_LookupTable] CHECK CONSTRAINT [FK_MainTable_LookupTable_LookupTable] 
GO 
ALTER TABLE [dbo].[MainTable_LookupTable] WITH CHECK ADD CONSTRAINT [FK_MainTable_LookupTable_MainTable] FOREIGN KEY([MainId]) 
REFERENCES [dbo].[MainTable] ([MainId]) 
GO 
ALTER TABLE [dbo].[MainTable_LookupTable] CHECK CONSTRAINT [FK_MainTable_LookupTable_MainTable] 
GO 

솔루션, 내 경우에는,이 코드

for (var i = 1; i < 3; ++i) 
{ 
    lookup = db.LookupTables.Local.FirstOrDefault(x => x.LookupId == i); 

    if (lookup == null) 
    { 
     lookup = new edmx.LookupTable() { LookupId = i }; 
     db.LookupTables.Attach(lookup); 
    } 

    main.LookupTables.Add(lookup); 
} 
에게 있습니다
using System; 
using System.Data.Entity; 
using System.Data.Entity.Core.Objects; 
using System.Data.Entity.Infrastructure; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      //remove then add it back, without select from the db 
      using (var db = new testing()) 
      { 
       var lookup = new edmx.LookupTable() { LookupId = 1 }; 

       var main = new edmx.MainTable() { MainId = 10 }; 
       main.LookupTables.Add(lookup); 

       db.LookupTables.Attach(lookup); 

       db.MainTables.Attach(main); 

       main.LookupTables.Remove(lookup); 

       db.SaveChanges(); 

       //imagine this is a loop from n to m and it happen that you have to add back something that you just deleted 
       lookup = new edmx.LookupTable() { LookupId = 1 }; 

       //crash if nothing 

       //db.Entry(lookup).State = EntityState.Unchanged; //crash 
       //db.LookupTables.Attach(lookup); //crash 

       if (!db.context.IsAttachedTo(lookup)) 
       { 
        //db.Entry(lookup).State = EntityState.Unchanged; //crash 
        //db.LookupTables.Attach(lookup); //crash 
       } 

       bool isDetached = db.Entry(lookup).State == EntityState.Detached; 
       if (isDetached) 
       { 
        //db.Entry(lookup).State = EntityState.Unchanged; //crash 
        //db.LookupTables.Attach(lookup); //crash 
       } 

       main.LookupTables.Add(lookup); 

       db.SaveChanges(); 
      } 

      Console.ReadKey(); 
     } 
    } 

    public partial class testing : edmx.testingEntities 
    { 
     public testing() 
      : base() 
     { 
      this.Database.Log = x => System.Diagnostics.Debug.Write(x); 
     } 
     public ObjectContext context 
     { 
      get { return (this as IObjectContextAdapter).ObjectContext; } 
     } 
    } 

    public static class helper 
    { 
     public static bool IsAttachedTo(this ObjectContext context, object entity) 
     { 
      ObjectStateEntry entry; 
      if (context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry)) 
      { 
       return (entry.State != EntityState.Detached); 
      } 
      return false; 
     } 
    } 
} 

답변

1

조회 인스턴스 (wi th id 1)이 여전히 EF에 연결되어 있으면 Remove (제거)는 main (10)과 lookup (1) 사이의 링크를 제거하는 것입니다.

조회 인스턴스를 다시 만들면 .NET에서는 다른 인스턴스이지만 데이터베이스/EF에서는 실제로 복제됩니다.

이전 조회 인스턴스를 다시 사용하거나 DbSet의 Local 속성을 사용하여 다시 찾아야합니다.

+0

감사합니다. 제 제안을 사용하여 내 "솔루션"으로 제 질문을 업데이트했습니다. – Fredou