2013-05-24 107 views
7

Tôi đang cố viết một truy vấn sẽ chiếu vào DTO trong đó hai thuộc tính là mảng int. Tôi nhận được một lỗi vì cuộc gọi ToArray() trong chiếu.LINQ to Entities không nhận ra ToArray

teams = context 
    .Teams 
    .Include("TeamDepartments") 
    .Include("TeamEmployees") 
    .Select(t => new TeamDto 
     { 
      sourceSystemId = t.TeamId, 
      name = t.Name, 
      manager = t.EmployeeIdTeamManager, 
      teamLead = t.EmployeeIdTeamLead, 
      employees = t.TeamEmployees.Select(te => te.EmployeeId).ToArray(), 
      departments = t.TeamDepartments.Select(td => td.DepartmentId).ToArray() 
     }) 
    .ToList(); 

Đối với nhân viên và phòng ban, là hai thuộc tính int [], làm cách nào tôi có thể nhận được các giá trị đó? Bây giờ, tôi chỉ cần kéo lại danh sách các nhóm và sau đó lặp lại chúng để tạo DTO.

Tôi đã nhìn thấy các câu hỏi tương tự khác, nhưng các giải pháp dường như không hoạt động đối với tôi. Tôi nghi ngờ có một bước bổ sung tôi cần phải thực hiện bởi vì tôi đang đi qua một mối quan hệ.

+1

Bạn có thể đăng TeamDto entitie không? – Fals

Trả lời

14

Những gì bạn cần làm là truy vấn riêng biệt này thành hai bước khác nhau; đầu tiên sẽ lấy kết quả chính xác, và thứ hai sẽ đưa dữ liệu vào DTO của bạn. Như thế này:

teams = context 
    .Teams 
    .Include("TeamDepartments") 
    .Include("TeamEmployees") 
    .Select(t => new // notice this is an anonymous object 
     { 
      sourceSystemId = t.TeamId, 
      name = t.Name, 
      manager = t.EmployeeIdTeamManager, 
      teamLead = t.EmployeeIdTeamLead, 
      employees = t.TeamEmployees.Select(te => te.EmployeeId), 
      departments = t.TeamDepartments.Select(td => td.DepartmentId) 
     }) 
    .ToList() // first run the query on the server without the ToArray calls 
    .Select(obj => new TeamDto 
     {  // then project the in-memory results onto your DTO. 
      sourceSystemId = obj.sourceSystemId, 
      name = obj.name, 
      manager = obj.manager, 
      teamLead = obj.teamLead, 
      employees = obj.employees.ToArray(), 
      departments = obj.departments.ToArray() 
     }) 
    .ToList(); 
+0

Có thể là do ToList() đầu tiên ngăn chặn chi phí, bạn có thể thực hiện Chọn từ kết quả truy vấn đầu tiên, đó là IQueryable. – Fals

+3

'ToList' đầu tiên là cần thiết vì truy vấn cần phải được chạy trên máy chủ trước cuộc gọi tiếp theo để' Select' chiếu tới DTO bằng cách sử dụng lệnh gọi 'ToArray', bởi vì các cuộc gọi đó không thể dịch sang SQL. –

+0

Tôi hiểu rồi! Cảm ơn bạn rất nhiều vì đã giải thích! – Fals

2

Tôi tin rằng vấn đề là bạn đang cố gọi ToArray trong khối mà nhà cung cấp SQL chuyển đổi thành truy vấn SQL. Tất nhiên, SQL Server không biết một mảng là gì để phương thức đó không hoạt động. Điều gì sẽ xảy ra nếu bạn xóa cuộc gọi ToArray? Tôi tin rằng những kết quả đó sẽ trở lại là IEnumberables bên ngoài khối đó, bạn có thể chuyển đổi chúng khi cần. Tôi không chắc chắn điều này sẽ làm việc nhưng nếu bạn thay đổi định nghĩa TeamDto của bạn theo cách sau nó có thể giải quyết vấn đề.

// you have now something like 
string[] employees; 
// instead do 
IEnumberable<string> employees; 
// If you want an array add 
string[] _employees; 

Sau đó, bên ngoài của truy vấn để _employees = employees.ToArray();

+0

đây là một vấn đề thường gặp khi chuyển đổi LINQ2Sql sang EF, vì Linq2Sql không cho phép bạn thực hiện điều này (tất nhiên SQL Server vẫn không giải thích lệnh gọi ToArray) –