2017-10-31 4 views
0

タスク:複数のmssqlテーブルにJSON応答を挿入複合JSONから複数のmssqlテーブルへ

問題:このジョブは永遠に実行されます。

現状:

[{ 
     "About": "", 
     "Name": "Employee_1", 
     "EmployeeId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", 
     "Address1": "Empstreet 4, 3. floor", 
     "Phone": "90909090", 
     "Birthdate": "1980-01-21", 
     "City": "Empcity", 
     "Zip": "8989", 
     "Competencies": [{ 
      "Name": "Tablet", 
      "ShortCode": "TAB", 
      "Status": false 
     }, { 
      "Name": "Flex", 
      "ShortCode": "FLX", 
      "Status": false 
     }], 
     "CustomColumns": [{ 
      "Description": "", 
      "Name": "", 
      "Type": "CheckBox", 
      "Value": "False" 
     }], 
     "CustomRoles": [{ 
      "CustomRoleModels": [{ 
       "IsAdminRole": false, 
       "IsEmployeeRole": false, 
       "IsPlannerRole": true, 
       "Name": "Shop Manager" 
      }], 
      "DepartmentId": "49664884-8382-4712-9953-fb36ca13fd1b" 
     }], 
     "HistoricalWages": [{ 
      "StartDate": "2000-01-01", 
      "Wage": 120 
     }], 
     "NotAvailable": [{ 
      "From": "12:00", 
      "To": "05:00", 
      "WeekDayIndex": 1 
     }, { 
      "From": "12:00", 
      "To": "04:00", 
      "WeekDayIndex": 0 
     }, { 
      "From": "12:00", 
      "To": "03:00", 
      "WeekDayIndex": 4 
     }, { 
      "From": "12:00", 
      "To": "05:00", 
      "WeekDayIndex": 3 
     }], 
     "Notes": [{ 
      "Author": "4a408a58-f9d6-4898-80a5-c3ef5667d2c6", 
      "Comment": "", 
      "Date": "2016-03-17" 
     }], 
     "Roles": [{ 
      "Admin": false, 
      "DepartmentId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", 
      "Employee": true, 
      "Planner": false 
     }] 
    }, { 
     "About": "", 
     "Name": "Employee_2", 
     "EmployeeId": "aaaaaaaa-bbbb-cccc-dddd-ffffffffffff", 
     "Address1": "Empstreet 5, 3. floor", 
     "Phone": "80808080", 
     "Birthdate": "1981-01-21", 
     "City": "Empcity", 
     "Zip": "8987", 
     "Competencies": [{ 
      "Name": "Tablet", 
      "ShortCode": "TAB", 
      "Status": false 
     }, { 
      "Name": "Flex", 
      "ShortCode": "FLX", 
      "Status": false 
     }], 
     "CustomColumns": [{ 
      "Description": "", 
      "Name": "", 
      "Type": "CheckBox", 
      "Value": "False" 
     }], 
     "CustomRoles": [{ 
      "CustomRoleModels": [{ 
       "IsAdminRole": false, 
       "IsEmployeeRole": false, 
       "IsPlannerRole": true, 
       "Name": "Shop Manager" 
      }], 
      "DepartmentId": "49664884-8382-4712-9953-fb36ca13fd1b" 
     }], 
     "HistoricalWages": [{ 
      "StartDate": "2000-01-01", 
      "Wage": 120 
     }], 
     "NotAvailable": [{ 
      "From": "12:00", 
      "To": "05:00", 
      "WeekDayIndex": 1 
     }, { 
      "From": "12:00", 
      "To": "04:00", 
      "WeekDayIndex": 0 
     }, { 
      "From": "12:00", 
      "To": "03:00", 
      "WeekDayIndex": 4 
     }, { 
      "From": "12:00", 
      "To": "05:00", 
      "WeekDayIndex": 3 
     }], 
     "Notes": [{ 
      "Author": "4a408a58-f9d6-4898-80a5-c3ef5667d2c6", 
      "Comment": "", 
      "Date": "2016-03-17" 
     }], 
     "Roles": [{ 
      "Admin": false, 
      "DepartmentId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", 
      "Employee": true, 
      "Planner": false 
     }] 
    }] 

と私はJSONコンテンツが中に保存されている次のクラス

public class Competency 
    { 
     public string Name { get; set; } 
     public string ShortCode { get; set; } 
     public bool Status { get; set; } 
    } 

public class CustomColumn 
{ 
    public string Description { get; set; } 
    public string Name { get; set; } 
    public string Type { get; set; } 
    public string Value { get; set; } 
} 

public class CustomRoleModel 
{ 
    public bool IsAdminRole { get; set; } 
    public bool IsEmployeeRole { get; set; } 
    public bool IsPlannerRole { get; set; } 
    public string Name { get; set; } 
} 

public class CustomRole 
{ 
    public List<CustomRoleModel> CustomRoleModels { get; set; } 
    public string DepartmentId { get; set; } 
} 

public class HistoricalWage 
{ 
    public string StartDate { get; set; } 
    public int Wage { get; set; } 
} 

public class NotAvailable 
{ 
    public string From { get; set; } 
    public string To { get; set; } 
    public int WeekDayIndex { get; set; } 
} 

public class Note 
{ 
    public string Author { get; set; } 
    public string Comment { get; set; } 
    public string Date { get; set; } 
} 

public class Role 
{ 
    public bool Admin { get; set; } 
    public string DepartmentId { get; set; } 
    public bool Employee { get; set; } 
    public bool Planner { get; set; } 
} 

public class Employees 
{ 
    public string About { get; set; } 
    public string Name { get; set; } 
    public string EmployeeId { get; set; } 
    public string Address1 { get; set; } 
    public string Phone { get; set; } 
    public string Birthdate { get; set; } 
    public string City { get; set; } 
    public string Zip { get; set; } 
    public List<Competency> Competencies { get; set; } 
    public List<CustomColumn> CustomColumns { get; set; } 
    public List<CustomRole> CustomRoles { get; set; } 
    public List<HistoricalWage> HistoricalWages { get; set; } 
    public List<NotAvailable> NotAvailable { get; set; } 
    public List<Note> Notes { get; set; } 
    public List<Role> Roles { get; set; } 
} 

を行っていることから:私はAPIから次のコンテンツの応答を取得

'json'という名前の変数は、次のように上記のクラスのクラスにデシリアライズされます:

機能下記の新しく作成されたオブジェクトが

private static void InsertDataToEmployees(List<Employees> allEmployees) 
{ 
    string connectionString = ConfigurationManager.ConnectionStrings["msEmployees"].ConnectionString; 
    List<Employees> records = allEmployees; 

    string insert_employee = "INSERT INTO dbo.dtEmployees (Name, EmployeeId, Address1, Phone, Birthdate, City, Zip) " + 
     " VALUES (@Name, @EmployeeId, @Address1, @Phone, @Birthdate, @City, @Zip)"; 

    string insert_competencies = "INSERT INTO dbo.dtCompetencies (EmployeeId, Name, ShortCode, Status) " + 
     " VALUES (@EmployeeId, @Name, @ShortCode, @Status)"; 

    string insert_available = "INSERT INTO dbo.dtAvailable (EmployeeId, [From], [To], WeekDayIndex) " + 
     " VALUES (@EmployeeId, @From, @To, @WeekDayIndex)"; 

    string insert_roles = "INSERT INTO dbo.dtRoles (EmployeeId, Admin, DepartmentId, Employee, Planner) " + 
     " VALUES (@EmployeeId, @Admin, @DepartmentId, @Employee, @Planner)"; 

    string insert_wages = "INSERT INTO dbo.dtWages (EmployeeId, StartDate, Wage) " + 
     " VALUES (@EmployeeId, @StartDate, @Wage)"; 

    using (SqlConnection conn = new SqlConnection(connectionString)) 
    { 
     conn.Open(); 

     foreach (var employee in allEmployees) 
     { 
      string empID = employee.EmployeeId; 

      using (SqlCommand cmd_employees = new SqlCommand(insert_employee, conn)) 
      { 
        cmd_employees.Parameters.AddWithValue("@Name", (object)employee.Name ?? DBNull.Value); 
        cmd_employees.Parameters.AddWithValue("@EmployeeId", (object)employee.EmployeeId ?? DBNull.Value); 
        cmd_employees.Parameters.AddWithValue("@Address1", (object)employee.Address1 ?? DBNull.Value); 
        cmd_employees.Parameters.AddWithValue("@Phone", (object)employee.Phone ?? DBNull.Value); 
        cmd_employees.Parameters.AddWithValue("@Birthdate", (object)employee.Birthdate ?? DBNull.Value); 
        cmd_employees.Parameters.AddWithValue("@Zip", (object)employee.Zip ?? DBNull.Value); 
        cmd_employees.Parameters.AddWithValue("@City", (object)employee.City ?? DBNull.Value); 
        cmd_employees.ExecuteNonQuery(); 
        cmd_employees.Parameters.Clear(); 
      } 

      foreach (var c in employee.Competencies) 
      { 
       using (SqlCommand cmd_competencies = new SqlCommand(insert_competencies, conn)) 
       { 
        cmd_competencies.Parameters.AddWithValue("@EmployeeId", (object)empID ?? DBNull.Value); 
        cmd_competencies.Parameters.AddWithValue("@Name", (object)c.Name ?? DBNull.Value); 
        cmd_competencies.Parameters.AddWithValue("@ShortCode", (object)c.ShortCode ?? DBNull.Value); 
        cmd_competencies.Parameters.AddWithValue("@Status", (object)c.Status ?? DBNull.Value); 
        cmd_competencies.ExecuteNonQuery(); 
        cmd_competencies.Parameters.Clear(); 
       } 
      } 

      foreach (var a in employee.NotAvailable) 
      { 
       using (SqlCommand cmd_available = new SqlCommand(insert_available, conn)) 
       { 
        cmd_available.Parameters.AddWithValue("@EmployeeId", (object)empID ?? DBNull.Value); 
        cmd_available.Parameters.AddWithValue("@From", (object)a.From ?? DBNull.Value); 
        cmd_available.Parameters.AddWithValue("@To", (object)a.To ?? DBNull.Value); 
        cmd_available.Parameters.AddWithValue("@WeekDayIndex", (object)a.WeekDayIndex ?? DBNull.Value); 
        cmd_available.ExecuteNonQuery(); 
        cmd_available.Parameters.Clear(); 
       } 
      } 

      foreach (var r in employee.Roles) 
      { 
       using (SqlCommand cmd_roles = new SqlCommand(insert_roles, conn)) 
       { 
        cmd_roles.Parameters.AddWithValue("@EmployeeId", (object)empID ?? DBNull.Value); 
        cmd_roles.Parameters.AddWithValue("@Admin", (object)r.Admin ?? DBNull.Value); 
        cmd_roles.Parameters.AddWithValue("@DepartmentId", (object)r.DepartmentId ?? DBNull.Value); 
        cmd_roles.Parameters.AddWithValue("@Employee", (object)r.Employee ?? DBNull.Value); 
        cmd_roles.Parameters.AddWithValue("@Planner", (object)r.Planner ?? DBNull.Value); 
        cmd_roles.ExecuteNonQuery(); 
        cmd_roles.Parameters.Clear(); 
       } 
      } 

      foreach (var w in employee.HistoricalWages) 
      { 
       using (SqlCommand cmd_wages = new SqlCommand(insert_wages, conn)) 
       { 
        cmd_wages.Parameters.AddWithValue("@EmployeeId", (object)empID ?? DBNull.Value); 
        cmd_wages.Parameters.AddWithValue("@StartDate", (object)w.StartDate ?? DBNull.Value); 
        cmd_wages.Parameters.AddWithValue("@Wage", (object)w.Wage ?? DBNull.Value); 
        cmd_wages.ExecuteNonQuery(); 
        cmd_wages.Parameters.Clear(); 
       } 
      } 
     } 
     conn.Close(); 
    } 
} 

機能の上に呼ばれると

List<Employees> employees = JsonConvert.DeserializeObject<List<Employees>>(json); 

は動作し、データをSQL Serverに同梱されますが、それは文字通り永遠にかかります。

私の質問は、ここでは専門家ではないので、JSONからMSSQLへの転送を達成する最も効率的な方法(時間に関して)は何ですか?

+0

の代わりに*行*ごとに単一の挿入を実行し、すべての挿入するためにSqlBulkCopyを使用最小限のロギングを使用して、データとしてストリームとして記録します。 SqlBulkCopyは、bcpと同じメカニズムを使用し、 'BULK INSERT' –

+0

ありがとう@PanagiotisKanavosはすぐにそれを行ってください。 – JaBoDK

答えて

0

遅延は、コードが行ごとに1つのコマンドを実行するために発生します。各行がどれほど小さいかを考えれば、ネットワークのラウンドトリップや個々の操作のログにほとんどすべての時間が無駄になります。

代わりにSqlBulkCopyを使用して、すべての行を最小限のロギングを使用してターゲット表に挿入されるレコードのストリームとして送信できます。

SqlBulkCopyは、DataTableまたはDbDataReaderを必要とします。代わりに、独自のDataTableとダブルバッファリングのすべての行を作成するか、独自のデータリーダーを書くのは、あなたのコレクションからのIDataReaderを作成するFastMemberパッケージを使用することができます。

using(var bcp = new SqlBulkCopy(connection)) 
using(var reader = ObjectReader.Create(allEmployees, "Name", "EmployeeId", "Address1", "Phone", "Birthdate", "City", "Zip")) 
{ 
    bcp.DestinationTableName = "dtEmployees"; 
    bcp.WriteToServer(reader); 
} 

場合は、プロパティ名とテーブルのフィールドドン」一致する場合は、ColumnMappingsプロパティにソース名とターゲット名を入力する必要があります。

あなたがSqlBulkCopyで使用することができ、コレクション、例えば取得するためにLINQを持つネストされたコレクションを平らにする必要があります:

var allCompetencies = from employee in allEmployees 
         from competency in employee.Competencies 
         select new { employee.EmpoyeeID, 
            competency.Name, 
            competency.ShortCode, 
            competency.Status}; 

using(var cmpBcp = new SqlBulkCopy(connection)) 
using(var var cmpReader=ObjectReader.Create(allCompetencies,"EmployeeID","Name","ShortCode","Status")) 
{ 
    cmpBcp.DestinationTableName = "dtCompetencies"; 
    cmpBcp.WriteToServer(cmpReader); 
} 
+0

完璧、ありがとう、魅力的なように働いた。 – JaBoDK

関連する問題