将 JSON 复杂到多个 mssql 表



>任务:将 JSON 响应插入多个 mssql 表中

问题:这项工作需要很长时间。

现状:

我从 API 收到以下内容响应:

[{
        "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
        }]
    }]

由此我制作了以下课程

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

JSON 内容存储在名为"json"的变量中,并反序列化为上述类类,如下所示:

List<Employees> employees = JsonConvert.DeserializeObject<List<Employees>>(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();
    }
}

上面的函数可以工作并将数据传送到SQL服务器,但实际上需要很长时间。

所以我的问题是,由于我绝不是这里的专家,那么完成 JSON 到 MSSQL 传输的最有效方法(就时间而言)是什么。

延迟是由于代码每行执行一个命令。考虑到每一行都很小,几乎所有时间都浪费在网络往返和单个操作的日志记录上。

您可以改用 SqlBulkCopy 将所有行作为记录流发送,这些记录流将使用最少日志记录插入到目标表中。

SqlBulkCopy 需要一个 DataTable 或 DbDataReader。无需创建自己的 DataTable 并对所有行进行双重缓冲,或者编写自己的数据读取器,您可以使用 FastMember 包从集合中创建 IDataReader:

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 属性。

您必须使用 LINQ 平展嵌套集合才能获得可与 SqlBulkCopy 一起使用的集合,例如:

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

相关内容

  • 没有找到相关文章

最新更新