2010-03-02 7 views
5

을 사용하여 INSERT INTO ... SELECT 수행 LINQ to SQL을 사용하여 "into ... select"형식 명령을 수행 할 수 있는지 파악하려고합니다. LINQ to SQL 코드를 사용하면 주어진 테이블에 여러 행을 삽입하는 단일 SQL 명령을 데이터베이스에 보낼 수 있습니다.LINQ to SQL

예를 들어, LINQ to SQL을 작성하는 방법은 다음 T-SQL 문을 SQL Server 데이터베이스로 보냅니다.

INSERT INTO Table1 
SELECT Table2.column1 + 1 AS column1, Table2.column2 + 2 AS column2 
WHERE Table2.column3 > 100 

나는 물론 DataContext.ExecuteCommand 기능을 사용하여이를 달성 할 수 있지만, 이것은 당신이 DataContext.SubmitChanges으로 얻을 처리 자동 트랜잭션을 활용하지 않고 즉시 실행됩니다. 이 업데이트 외에 일련의 업데이트가 있으며 오류가 발생하면 롤백해야합니다.

아이디어가 있으십니까?

UPDATE : 여기에 실제 코드는 다음과 같습니다

 var bs_prep = 
      from b in dc.T_EDR_FILEBODies 
      join 
      unpaid in dc.V_UNPAIDs 
      on 
       b.NUM_ADC.Substring(1, 9) equals unpaid.NOCONT 
      join 
      acordo in dc.T_ACORDOS_RECOM_APREs 
      on 
       Convert.ToInt32(b.NUM_ADC.Substring(1, 9)) equals acordo.ID_Contrato 
      where 
       b.ID_EDR == id_edr 
       && 
       (
        unpaid.NUM_INCUMPRIMENTOS <= max_unpaid_consec 
        && 
        unpaid.TOTAL_NUM_INCUPRIMENTOS <= max_unpaid_nonconsec 
       ) 
       || 
       (
        acordo.Activo == true 
        && 
        acordo.Data_Recomeco <= now 
       ) 
      select new 
       { 
        ID_EDR = id_edr_filt, 
        NUM_LINHA = b.NUM_LINHA, 
        CODREJ = b.CODREJ, 
        HDT = b.HDT, 
        IMPORT = b.IMPORT, 
        NIB_DEV = b.NIB_DEV, 
        NUM_ADC = b.NUM_ADC, 
        REF_DD_BC = b.REF_DD_BC, 
        REF_MOV = b.REF_MOV 
       } 
      ; 


     dc.T_EDR_FILEBODies.InsertAllOnSubmit(
      bs_prep.Select(
       b => new T_EDR_FILEBODY{ 
        CODREJ = b.CODREJ, 
        HDT = b.HDT, 
        ID_EDR = b.ID_EDR, 
        IMPORT = b.IMPORT, 
        NIB_DEV = b.NIB_DEV, 
        NUM_ADC = b.NUM_ADC, 
        NUM_LINHA = b.NUM_LINHA, 
        REF_DD_BC = b.REF_DD_BC, 
        REF_MOV = b.REF_MOV 
       } 
      ) 
     ); 

빠른 설명 : T_EDR_FILEBODies 개체는 기본적으로 우리가 가져올 텍스트 파일의 내용을 저장하는 데이터베이스 테이블에 매핑됩니다. 하나의 레코드는 텍스트 파일의 한 줄에 해당합니다.

내가하려는 것은 파일의 레코드를 하나의 파일에서 복사하여 새로운 파일 ID (ID_EDR=id_edr_filt)를 제공하지만 일부 줄을 필터링하여 파일 내용의 필터링 된 버전을 만드는 것입니다. LINQ to SQL 엔터티는 데이터베이스 테이블에 직접 매핑됩니다. 지금까지 datacontext에 코드를 추가하지 않았습니다. 그들은 기본 키를 가지고, 그렇지 않으면 내가 그들에 삽입을 할 수 없을 것입니다 (나는 어딘가에 내가 기본 키를 없애면 그 예외를 제거 할 수있을 것이라고 읽을 수 있지만 볼 수 있듯이, 그것은 내 경우에는 작동). 개체 유형 쿼리에 'T_EDR_FILEBODY'의

명시 건축이 허용되지 않은 : 나는 그것을 실행하면

나는 InsertAllOnSubmit에 의해 슬로우 다음과 같은 예외를 얻을.

쿼리 내부에 명시 적으로 엔티티를 구성하는 것이 문제가 될 것이라고 생각합니다. 쿼리에 의해 리턴 된 엔티티는 변경 추적을 가지며, 변경 사항은 submitchanges가 호출 될 때 데이터베이스로 변환됩니다. 그러나 클라이언트 측에서 생성 된 엔티티의 변경 사항을 어떻게 데이터베이스로 변환 할 수 있습니까? 그러나 이것은 정말로 당신이 LINQ to SQL을 사용하여 INSERT INTO ... SELECT 타입 명령을 수행 할 수 없다는 것을 의미합니까?

+1

당신이 할 수를 상기 ExecuteCommand를하고 그 안에 어떤 다른 사람을 "새 TransactionScope에로 _tx 사용()"및 포장? – StingyJack

+0

글쎄, 내가 할 수있는 것 같아요, 그리고 난 그냥 까다롭게 수 있지만 난 당신이 그냥 ... linq를 사용하여 성명을 삽입을 할 수 없다는 것을 받아 들일 것을 발견. 그것은 거대한 handycap 일 것입니다. –

답변

0

당신은

ctx.Table1.InsertAllOnSubmit(
    mySelectEnumeration.Select(x => new Table1DT { ... }) 
); 
  • InsertAllOnSubmit는 SQL 테이블에 Linq에에 항목의 번호를 삽입 할 수 있습니다.
  • mySelectEnumeration은 삽입 할 항목을 선택하는 쿼리입니다.
  • Select(new Table1DT { ... })은 선택 쿼리의 데이터 유형을 테이블의 데이터 유형으로 변환하는 데 필요한 변환입니다.

또는 ExecuteCommand 방법을 사용하고 수동으로 트랜잭션을 관리 할 수 ​​있습니다.

using (var ctx = new DataClasses1DataContext()) { 
    ctx.Connection.Open(); 
    using (ctx.Transaction = ctx.Connection.BeginTransaction()) { 
     ctx.ExecuteCommand("sqlcommand"); 
     ctx.Transaction.Commit(); 
    } 
} 

또는 거래 범위 사용 :

using (var ctx = new DataClasses1DataContext()) { 
    using (var scope = new TransactionScope()) { 
     ctx.ExecuteCommand("sqlcommand"); 
     scope.Complete(); 
    } 
} 
+0

나는 당신의 제안을 받아들이지 않을지 확신하지 못합니다. mySelectEnumeration을 기반으로 인라인 생성자에서 Table1DT 인스턴스를 초기화하는 방법을 볼 수 없습니다. mySelectEnumeration은 어떻게 참조합니까? 또는 Select 절의 Table1DT 인라인 생성자를 사용하는 다른 쿼리에서 첫 번째 쿼리 (IQueryable 반환)를 캡슐화하려고 시도 했으므로 IQueryable 을 반환합니다. 하지만 나는 동일한 오류가 발생하여 첫 번째 쿼리에 인라인 생성자를 넣습니다. 쿼리에서 'Table1DT'엔터티 형식의 명시 적 생성이 허용되지 않습니다. –

+1

필자의 구체적인 DataContext 클래스 (내 샘플에서는 ctx)를 알지 못해 placeholder를 사용했습니다. 'Table1'은 테이블에 대한 항목이 삽입되어야하는 자리 표시 자입니다. mySelectEnumeration은 삽입하려는 항목을 선택하기 위해 수행 한 쿼리의 결과입니다. 'Table1DT'는'Table1'의 데이터 타입입니다. 그리고 '...'는 "Table1"의 속성을 어디에 설정해야 하는지를 나타냅니다. 'ID = x.identifier'. 나는 당신의 DataContext를 알지 못하면 더 구체적 일 수 없다. – AxelEckenberger

+0

오케이 제 실수입니다. 필자의 답을 철저히 읽지는 못했을 것입니다. ("x =>"를 놓쳤습니다.) 확인을 시도하고 InsertAllOnSubmit 호출에 대해 동일한 예외가 여전히 있습니다. 쿼리에서 엔터티 형식 'Table1DT'의 명시 적 생성이 허용되지 않습니다. (내가 사용한 표기법을 사용하고 있습니다). 나는 이것에 대해 읽었고 어떤 이유로 당신이 질의 내부에 엔티티를 만들 수 없다는 생각이 들었다. 이유는 모르겠다. –