2013-04-19 22 views
13

Tôi có một cấu trúc lớp tương tự như sau:Tôi có thể trả về một bộ sưu tập của nhiều loại nguồn gốc từ truy vấn Dapper

public abstract class Device 
{ 
    public int DeviceId { get; set; } 
    //Additional Properties 
} 

public class DeviceA : Device 
{ 
    //Specific Behaviour 
} 

public class DeviceB : Device 
{ 
    //Specific Behaviour 
} 

tôi cần phải lấy một danh sách các thiết bị, hoặc một thiết bị duy nhất mà được khởi tạo là phù hợp loại có nguồn gốc (dựa trên giá trị Type trong Record Device trong DB). Tức là, bộ sưu tập của các đối tượng Device phải chứa một số đối tượng có các loại khác nhau, tất cả đều có nguồn gốc từ Device.

Tôi đã thực hiện điều này theo cách sau, nhưng có điều gì đó không cảm thấy đúng về nó.

public static IEnumerable<Device> AllDevices() 
{ 
    using (var connection = CreateConnection()) 
    { 
     connection.Open(); 
     return connection.Query<dynamic>("SELECT * FROM Device").Select<dynamic, Device>(d => 
      { 
       Device device = null; 
       if (d.DeviceTypeID == 1) 
        device = new DeviceA(); 
       else if (d.DeviceTypeID == 2) 
        device = new DeviceB(); 
       else throw new Exception("Unknown Device"); 
       device.DeviceId = d.DeviceID; 
       return device; 
      }); 
    } 
} 

Đây có phải là cách chính xác để đạt được điều này bằng Dapper hoặc có cách tiếp cận tốt hơn không?

+0

Có thể dễ đọc hơn nếu bạn chia truy vấn thành 2 truy vấn riêng biệt. Một trong DeviceType 1 và một cho deviceType 2, sau đó kết hợp hai tập kết quả cho sự trở lại của bạn, nhưng khác hơn, điều này có vẻ là một giải pháp tốt. – DavidEdwards

+0

Không thực sự những gì tôi đang tìm kiếm - đặc biệt đối với trường hợp sử dụng khi truy xuất một thiết bị duy nhất, vì chúng tôi không biết loại thiết bị trước thời hạn. (ví dụ: Nhận thiết bị theo số sê-ri hoặc một số số nhận dạng khác). Cảm ơn, mặc dù, David. – GaryJL

+0

Nếu bạn quan tâm đến việc theo dõi tiến trình trên tính năng này: https://github.com/StackExchange/dapper-dot-net/issues/262 – ajbeaven

Trả lời

3

Trong phiên bản hiện tại có lẽ là tùy chọn duy nhất (đặc biệt là vì loại cơ sở là trừu tượng). Tuy nhiên, sẽ không có lý do gì khi nghĩ đến các cách đề xuất một hệ thống kế thừa phân biệt đối xử. Nó không phải là một cái gì đó chúng tôi đã làm cho đến nay chỉ đơn giản bởi vì nó đã không đưa ra - nhưng nó không âm thanh không thể. Vấn đề lớn nhất mà tôi có thể nhìn thấy (khác với IL-wrangling, rõ ràng) chỉ đơn giản là cách chúng tôi thể hiện mối quan hệ.

+0

Cảm ơn, Marc. Sự khác biệt là gì nếu loại cơ sở không trừu tượng? – GaryJL

+0

@GaryJL Tôi đã không thực sự đề cập đến trừu tượng; tại thời điểm nó sẽ chỉ tạo ra kiểu khai báo (có lẽ là kiểu cơ sở); nếu có cái gì đó "thông minh" đang diễn ra, tôi sẽ mong đợi các loại cơ sở trừu tượng hoạt động, miễn là nó không bao giờ cần tạo loại đó, rõ ràng là # –

+1

Tôi ngạc nhiên rằng điều này chưa từng xảy ra trước đây. Dường như với tôi rằng thừa kế như thế này là khá phổ biến trong nhiều cơ sở dữ liệu. – ajbeaven

0

Tôi đã nảy ra giải pháp này:

using (IDbConnection db = new MySqlConnection(ConfigurationManager.ConnectionStrings["yourConnection"].ConnectionString)) 
     { 
      return db.Query<dynamic, DeviceA, DeviceB, Device>(@" 
       Select 
        Discriminator, 
        ... 
       From Device", (d, da, db) => 
       { 
        if (p.Discriminator == "DeviceA") 
        { 
         return new DeviceA(); 
        } 
        else if (p.Discriminator == "DeviceB") 
        { 
         return new DeviceB(); 
        } 
        return d; 
       });  

Âm thanh phức tạp, nhưng nó hoạt động!

Hy vọng nó có thể giúp bạn. }

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