Comment puis-je faire SqlBulkCopy quand il y a une dépendance dans la table?

c# sqlbulkcopy

Question

Je suis capable de faire SqlBulkCopy quand il n'y a aucune dépendance sur la table avec le code ci-dessous:

//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);
                    }
                }
            }
        }

Cependant, quand il y a une dépendance, je suis confus. dépendance

1) Dois-je créer un DataTable pour chaque table?

2) Puisque les informations de relation entre les tables sont fournies par l'utilisateur et chargées en mémoire, comment puis-je lier des tables sans lire les informations du schéma? ou Dois-je lire les informations et obtenir la clé primaire de Schema?

Merci d'avance. J'espère avoir été clair.

Réponse acceptée

Dans des situations comme celle-ci, la seule façon de procéder consiste à effectuer vos opérations de copie en bloc sur des tables temporaires sans aucune clé reliant les deux objets (et suffisamment de métadonnées pour créer les liens ultérieurement).

Disons que vous avez 3 tables: #item_unit_staging , #shop_order_staging et #shop_order_operation_staging . Vous les item_unit avec le même schéma que vos item_unit , shop_order et shop_order_operation avec des clés primaires générées automatiquement. Vous voudriez également ajouter toutes les données que vous avez utilisées pour lier les données en mémoire sur votre machine locale en tant que "colonne de métadonnées", disons que nous avons utilisé une colonne supplémentaire appelée metadata_id sur les trois tables et une colonne appelée parent_id sur #shop_order_staging et #shop_order_operation_staging .

Nous insérons ensuite en bloc dans nos 3 tables, en remplissant nos colonnes de clé primaire et en laissant nos colonnes de clé étrangère à NULL . Une fois que nous avons les données sur le serveur, nous utilisons les colonnes de métadonnées pour renseigner les colonnes de clé étrangère.

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

Vous pouvez ensuite copier les données des tables temporaires dans les tables réelles

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


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi