2013-04-19 5 views
13

Mam struktury klasowej podobny do tego:mogę wrócić zbiór wielu Derived ów Dapper zapytania

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

public class DeviceA : Device 
{ 
    //Specific Behaviour 
} 

public class DeviceB : Device 
{ 
    //Specific Behaviour 
} 

muszę pobrać listę urządzeń lub pojedynczego urządzenia, które jest tworzony jako właściwy typ pochodny (w oparciu o wartość typu w rekordzie urządzenia w bazie danych). Oznacza to, że zbiór obiektów Device powinien zawierać wiele obiektów o różnych typach, z których wszystkie pochodzą od Device.

Wdrożyłem to w następujący sposób, ale coś po prostu nie jest w porządku z tym.

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

Czy jest to właściwy sposób osiągnięcia tego przy pomocy narzędzia Dapper, czy też istnieje lepsze podejście?

+0

Może być bardziej czytelny, jeśli podzielisz zapytanie na 2 osobne zapytania. Jeden z DeviceType 1 i jeden dla deviceType 2, po czym połączył dwa zestawy wyników dla twojego powrotu, ale poza tym wydaje się to dobrym rozwiązaniem. – DavidEdwards

+0

Niezupełnie tego, czego szukam - szczególnie w przypadku użycia podczas pobierania pojedynczego urządzenia, ponieważ nie znamy typu urządzenia z wyprzedzeniem. (Pobierz urządzenie według numeru seryjnego lub innego identyfikatora). Dzięki, David. – GaryJL

+0

Jeśli chcesz śledzić postępy w tej funkcji: https://github.com/StackExchange/dapper-dot-net/issues/262 – ajbeaven

Odpowiedz

3

W obecnej wersji jest prawdopodobnie jedyną opcją (zwłaszcza, że ​​typ podstawowy jest abstrakcyjny). Jednak nie byłoby nierozsądne wymyślanie sposobów sugerowania dyskryminowanego systemu dziedziczenia. To nie jest coś, co zrobiliśmy do tej pory tylko dlatego, że się nie pojawił - ale nie brzmi to niemożliwe. Największym problemem, jaki widzę (oczywiście innym niż kłócenie się z ILem) jest po prostu to, jak wyrażamy związek.

+0

Dzięki, Marc. Jaka byłaby różnica, gdyby typ podstawowy nie był abstrakcyjny? – GaryJL

+0

@GaryJL Nie wspomniałem o abstrakcji; w tej chwili po prostu stworzy zadeklarowany typ (przypuszczalnie typ bazowy); gdyby było coś bardziej "sprytnego", spodziewałbym się, że abstrakcyjne typy bazowe zadziałają, o ile nigdy nie będą musiały tworzyć tego typu, oczywiście # –

+1

Jestem zaskoczony, że tak się nie stało. Wydaje mi się, że dziedziczenie takie jak to jest dość powszechne w wielu bazach danych. – ajbeaven

0

ja wymyślił tego rozwiązania:

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

Dźwięki trudne, ale to działa!

Mam nadzieję, że ci to pomoże. }