테이블에 종속성이있을 때 어떻게 SqlBulkCopy를 할 수 있습니까?

c# sqlbulkcopy

문제

아래 코드를 사용하여 테이블에 대한 종속성이 없을 때 SqlBulkCopy를 수행 할 수 있습니다.

//TableData and FieldData have column info in memory.  
using (SqlConnection connection = new SqlConnection(@"Data Source=WLO1;Initial Catalog=GenTest2;Integrated Security=True"))
        {

            connection.Open();
            foreach (string tableName in tablesInOrderToProcess)
            {
                if (tableDataList.ContainsKey(tableName))
                {
                    TableData td = tableDataList[tableName];

                    SqlBulkCopy copy = new SqlBulkCopy(connection);
                    copy.BatchSize = 10000;
                    copy.DestinationTableName = tableName;

                    System.Data.DataTable dt = new DataTable();
                    foreach (FieldData fd in td.FieldList.Values)
                    {
                        string fieldName = fd.Name;
                        string fieldDataType = fd.DataType;
                        string fieldSize = fd.Size.ToString(); ;
                        string fieldConstant = fd.constantValue;
                        string fieldAverage = fd.averageSize;
                        string fieldPickList = fd.pickList;
                        copy.ColumnMappings.Add(fieldName, fieldName);
                        switch (fieldDataType)
                        {
                            case "char":
                                {
                                    dt.Columns.Add(fieldName, System.Type.GetType("System.String"));
                                }
                                break;
                            case "nvarchar":
                                {
                                    dt.Columns.Add(fieldName, System.Type.GetType("System.String"));
                                }
                                break;
                            case "number":
                                {
                                    if (fd.Size == 10)
                                        dt.Columns.Add(fieldName, System.Type.GetType("System.Int64"));
                                    else
                                        dt.Columns.Add(fieldName, System.Type.GetType("System.Int32"));
                                }
                                break;
                            default:
                                {
                                    dt.Columns.Add(fieldName);
                                }
                                break;
                        }
                    }
                    for (int i = 0; i < int.Parse(td.NumRows); i++)
                    {
                        System.Data.DataRow r = dt.NewRow();
                        foreach (FieldData fd in td.FieldList.Values)
                        {
                            string fieldName = fd.Name;
                            string fieldDataType = fd.DataType;
                            string fieldSize = fd.Size.ToString(); ;
                            string fieldConstant = fd.constantValue;
                            string fieldAverage = fd.averageSize;
                            string fieldPickList = fd.pickList;

                            switch (fieldDataType)
                            {
                                case "char":
                                    {
                                        if (fd.averageSize.Length > 0)
                                        {
                                            r[fieldName] = GetRandomString(Int32.Parse(fd.averageSize), true);
                                        }
                                        else
                                        {
                                            r[fieldName] = fieldConstant;
                                        }
                                    }
                                    break;
                                case "nvarchar":
                                    {
                                        if (fd.averageSize.Length > 0)
                                        {
                                            r[fieldName] = GetRandomString(Int32.Parse(fd.averageSize), true);
                                        }
                                        else
                                        {
                                            r[fieldName] = fieldConstant;
                                        }
                                    }
                                    break;
                                case "number":
                                    {
                                        if (fd.Size == 10)
                                        {
                                            r[fieldName] = i;
                                        }
                                        else
                                        {
                                            r[fieldName] = i;
                                        }
                                    }
                                    break;
                                default:
                                    {
                                        r[fieldName] = fieldConstant;
                                    }
                                    break;
                            }

                        }
                        dt.Rows.Add(r);
                    }

                    try
                    {
                        copy.WriteToServer(dt);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            }
        }

그러나, 의존성이있을 때 나는 혼란 스럽다. 의존

1) 각 테이블에 대해 DataTable을 만들어야합니까?

2) 테이블 관계 정보는 사용자가 제공하고 메모리에로드되므로 스키마의 정보를 읽지 않고 테이블을 어떻게 묶을 수 있습니까? 또는 정보를 읽고 스키마에서 기본 키를 가져야합니까?

미리 감사드립니다. 나는 그것을 분명히하기를 희망한다.

수락 된 답변

이와 같은 상황에서 수행 할 수있는 유일한 방}은 두 오브젝트를 링크하는 키가없고 (나중에 링크를 빌드하기에 충분한 메타 데이터) 임시 테이블로 대량 복사 조작을 수행하는 것입니다.

#item_unit_staging , #shop_order_staging#shop_order_operation_staging 테이블이 3 개 있다고 가정 #shop_order_operation_staging . item_unit , shop_ordershop_order_operation 과 동일한 스키마를 사용하여 자동 생성 기본 키를 사용하여 항목을 작성하십시오. 또한 로컬 컴퓨터의 메모리에있는 데이터를 "메타 데이터 열"로 연결하는 데 사용 된 데이터를 추가하고자 할 때, 세 테이블 모두에서 metadata_id 라는 추가 열과 #shop_order_staging parent_id 라는 열을 사용한다고 가정 할 수 있습니다 #shop_order_operation_staging .

그런 다음 기본 키 열이 채워지고 외래 키 열이 NULL 3 개의 테이블에 대량 삽입 NULL . 서버에 데이터를 가져 오면 메타 데이터 열을 사용하여 외래 키 열을 채 웁니다.

update #shop_order_staging 
    set parent_item_unit_id = #item_unit_staging.item_unit_id
    from #shop_order_staging
    inner join #item_unit_staging on #shop_order_staging.parent_id = #item_unit_staging.metadata_id

update #shop_order_operation_staging 
    set parent_shop_order_id = #shop_order_staging.shop_order_id
    from #shop_order_operation_staging
    inner join #shop_order_staging on #shop_order_operation_staging.parent_id = #shop_order_staging.metadata_id

그런 다음 임시 테이블의 데이터를 실제 테이블로 복사 할 수 있습니다

insert into item_unit 
    select item_unit_id
         , /*all other columns except [metadata_id]*/ 
    from #item_unit_staging


insert into shop_order 
    select shop_order_id
         , parent_item_unit_id
         , /*all other columns except metadata_id and parent_id*/ 
    from #shop_order_staging

insert into shop_order_operation 
    select shop_order_operation_id
         , parent_shop_order_id
         , /*all other columns except metadata_id and parent_id*/ 
    from #shop_order_operation_staging


아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.