2016-05-13 62 views
10

Tôi có hai bảng:Làm thế nào để sao chép dữ liệu từ SQL Object C# mẫu tài sản

  • nhân viên: Id, Name, DepartmentId
  • cục: Id, Name

Employee.cs:

public int Id {get;set;} 
public string Name {get;set;} 
public int DepartmentId {get;set;} 

Department.cs:

public int Id {get;set;} 
public string Name {get;set;} 

ViewModel: EmployeeDepartmentVM:

public Department department {get;set;} 
public List<Employee> employees {get;set;} 

Để Tham gia hai bảng này tôi đã viết mã này:

SELECT E.* , D.Id as DId , D.Name as DName 
    from [Employee] as E 
    LEFT OUTER JOIN [Department] as D 
    ON E.DepartmentId = D.Id 
    where D.Id = 1 

Làm thế nào để tôi nhận được EmployeeDepartmentVM loại từ trên truy vấn?

Tôi biết nếu tôi viết một mô hình như vấn đề của tôi sẽ được giải quyết:

public int Id {get;set;} 
public string Name {get;set;} 
public int DepartmentId {get;set;} 
public int DId {get;set;} 
public string Name {get;set;} 

Nhưng tôi không muốn viết thêm mô hình. Đơn giản chỉ cần dữ liệu truy vấn liên kết vào loại EmployeeDepartmentVM.

+1

Bạn có thể sử dụng phản chiếu để điền thuộc tính. http://stackoverflow.com/questions/1089123/setting-a-property-by-reflection-with-a-string-value –

+1

Khi LEFT JOIN, đặt các điều kiện của bảng bên phải trong mệnh đề ON để thực hiện đúng hành vi kết nối trái . (Khi trong WHERE bạn nhận được kết quả bên trong thường xuyên tham gia.) I.e làm '... ON E.DepartmentId = D.Id AND D.Id = 1'. – jarlh

+1

Tại sao bạn không thích sử dụng EF ..? Bạn phải viết nhiều mã hơn, nếu bạn không sử dụng ORM này .. – Karthick

Trả lời

7

Tôi thực sự không thấy thử thách là gì. Định nghĩa EmployeeDepartmentVM ngụ ý rằng bạn cần nhóm nhóm kết quả theo số Department. Giả sử tập kết quả là không có thứ tự, nó có thể đạt được bằng cách đơn giản duy trì một từ điển để định vị các mô hình khung nhìn của các bộ phận đã được thêm vào trong khi đọc.

nào dẫn đến một cái gì đó như thế này:

static List<EmployeeDepartmentVM> GetEmployeeDepartmentVMList(DbCommand command) 
{ 
    var resultById = new Dictionary<int, EmployeeDepartmentVM>(); 
    using (var reader = command.ExecuteReader()) 
    { 
     var employeeIdCol = reader.GetOrdinal("Id"); 
     var employeeNameCol = reader.GetOrdinal("Name"); 
     var departmentIdCol = reader.GetOrdinal("DId"); 
     var departmentNameCol = reader.GetOrdinal("DName"); 
     while (reader.Read()) 
     { 
      var departmentId = reader.GetInt32(departmentIdCol); 
      EmployeeDepartmentVM result; 
      if (!resultById.TryGetValue(departmentId, out result)) 
      { 
       result = new EmployeeDepartmentVM 
       { 
        department = new Department(), 
        employees = new List<Employee>() 
       }; 
       result.department.Id = departmentId; 
       result.department.Name = reader.GetString(departmentNameCol); 
       resultById.Add(departmentId, result); 
      } 
      var employee = new Employee(); 
      employee.Id = reader.GetInt32(employeeIdCol); 
      employee.Name = reader.GetString(employeeNameCol); 
      employee.DepartmentId = departmentId; 
      result.employees.Add(employee); 
     } 
    } 
    return resultById.Values.ToList(); 
} 

Một số điều cần lưu ý. Cách viết, truy vấn SQL của bạn ngụ ý rằng các trường liên quan đến Bộ có thể là null (LEFT OUTER JOIN). Tuy nhiên, mệnh đề WHERE và mô hình Nhân viên (trường DepartmentId không thể vô hiệu) ngụ ý rằng nó không thể xảy ra. Nếu mục đích là để bao gồm các phòng ban không có nhân viên, sau đó tốt hơn thay đổi tham gia để RIGHT OUTER và sử dụng một cái gì đó như thế này:

// ... 
if (reader.IsDBNull(employeeIdCol)) continue; 
var employee = new Employee(); 
// ... 

EDIT: Để hoàn chỉnh, đây là cách tiếp cận khác. Nó tương tự như cách EF materializes truy vấn tương tự và không cần từ điển tạm thời, nhưng đòi hỏi đầu vào thiết lập để được sắp xếp theo PK của bảng tổng thể, vì vậy bạn cần phải thêm

ORDER BY D.Id 

ở phần cuối của SQL của bạn . Cơ sở dữ liệu có thể dễ dàng và hiệu quả cung cấp thứ tự như vậy, và lợi ích của giải pháp này là nó cho phép thực hiện hoãn lại và không yêu cầu xử lý toàn bộ thiết lập để bắt đầu trả về kết quả. Nó không cần thiết nếu bạn muốn chỉ nhận được một danh sách, nhưng có thể hữu ích trong các tình huống khác.

static IEnumerable<EmployeeDepartmentVM> GetEmployeeDepartmentVMs(DbCommand command) 
{ 
    using (var reader = command.ExecuteReader()) 
    { 
     var employeeIdCol = reader.GetOrdinal("Id"); 
     var employeeNameCol = reader.GetOrdinal("Name"); 
     var departmentIdCol = reader.GetOrdinal("DId"); 
     var departmentNameCol = reader.GetOrdinal("DName"); 
     for (bool more = reader.Read(); more;) 
     { 
      var result = new EmployeeDepartmentVM 
      { 
       department = new Department(), 
       employees = new List<Employee>() 
      }; 
      result.department.Id = reader.GetInt32(departmentIdCol); 
      result.department.Name = reader.GetString(departmentNameCol); 
      do 
      { 
       if (reader.IsDBNull(employeeIdCol)) continue; 
       var employee = new Employee(); 
       employee.Id = reader.GetInt32(employeeIdCol); 
       employee.Name = reader.GetString(employeeNameCol); 
       employee.DepartmentId = result.department.Id; 
       result.employees.Add(employee); 
      } 
      while ((more = reader.Read()) && reader.GetInt32(departmentIdCol) == result.department.Id); 
      Debug.Assert(!more || reader.GetInt32(departmentIdCol) > result.department.Id); // Sanity check 
      yield return result; 
     } 
    } 
} 

Để có danh sách như cách tiếp cận đầu tiên, chỉ cần thêm ToList() sau cuộc gọi, ví dụ:

var result = GetEmployeeDepartmentVMs(command).ToList(); 
+0

ya. Nó làm việc cho tôi. Một câu hỏi. Tôi có thể sử dụng Danh sách thay vì từ điển không? –

+1

Bạn có thể, nhưng nó sẽ không hiệu quả nếu bạn không áp dụng bộ lọc bộ phận. Việc triển khai nhóm thường sử dụng một số loại cấu trúc dữ liệu băm (như Từ điển) hoặc các bộ kết quả được sắp xếp (như EF). Từ điển chỉ là tạm thời, như bạn có thể thấy, tôi đang chuyển đổi nó thành danh sách ở cuối. –

Các vấn đề liên quan