2011-12-05 64 views
2

我決定使用Dapper.net,因爲它似乎只做我想做的事情:映射,我不需要任何幻想,我只是無聊處理我的數據傳遞者和我之間的映射目的。繼承和Dapper.net

我的問題:

比方說,我有這些類:

class Foo{ 
int ID; 
string Name; 
} 
class Bar : Foo{ 
string FavoriteMoovie; 
} 

而且這些表:

Foo 
- ID 
- Name 

Bar 
- FooID 
- FavoriteMoovie 

所以我想知道我可以選擇我的Foo和同一個查詢中的酒吧?

我唯一的想法到目前爲止是

  • 選擇所有不在酒吧
  • 然後選中所有酒吧

我不能使用該方法的重載的FOOS「查詢「因爲這裏只是爲了映射關係。

+0

這不是像http://stackoverflow.com/q/8344591/75642一樣的問題,只是它是關於Dapper的? –

+0

正如我所說在我的上一個問題,我不得不從petapoco搬出,因爲這是petapoco不可能的。正如我在這裏所說的,我有一個解決方案與Dapper,但我正在尋找這個工具更好的一個 –

回答

1

很hacky,但這可能有效。

db.Query<Bar, object, Foo>("select * from Foo left join Bar on FooID = ID", 
(bar,ignore) => 
    bar.FavoriteMoovie == null ? bar : new Foo{ID = bar.ID, Name = bar.Name}); 

缺點是它創建了幾個中間對象,它可以不用。

其他選項是簡單地選擇Bar對象,然後使用相同的技巧過濾出Foos或選擇動態,然後轉換爲正確的類。

就我個人而言,我不會查詢兩次只是爲了處理這個問題,除非您允許使用NULL FavoriteMoovie,在這種情況下,您別無選擇,只能使查詢複雜化或選擇兩次。

的情況下
+0

我做了一個多重選擇來處理這個「SELECT * INTO #temp FROM Foo; SELECT * FROM #temp where not exist (..)select * from #temp innter join bar on ...「 –

0

當每一個分層TPH一個表,很容易讓所有混凝土孩子的類,特別是如果BaseClass的是抽象的

abstract class BaseValue 
{ 
    public BaseValue() 
     : this(0, 0, string.Empty) 
    { 
    } 

    public BaseValue(int id, double value, string dimension) 
    { 
     Id = id; 
     TypeName = GetType().Name; 
     Dimension = dimension; 
     _value = value; 
    } 

    protected double _value; 

    public double RawValue 
    { 
     get { return _value; } 
    } 

    public int Id { get; protected set; } 

    public string TypeName { get; protected set; } 

    public string Dimension { get; set; } 

} 

abstract class BaseValue<T> : BaseValue 
    where T : struct 
{ 
    public BaseValue() 
     : this(0, default(T), string.Empty) 
    { } 

    public BaseValue(int id, T value, string dimension) 
     : base(id, 0, dimension) 
    { 
     Value = value; 
    } 

    public T Value 
    { 
     get 
     { 
      if (typeof(T) == typeof(float)) 
       return (dynamic)(float)_value; 
      else if (typeof(T) == typeof(bool)) 
       return (dynamic)(bool)(_value > 0 ? true : false); 
      else if (typeof(T) == typeof(int)) 
       return (dynamic)(int)_value; 
      else if (typeof(T) == typeof(TimeSpan)) 
       return (dynamic)TimeSpan.FromSeconds(_value); 
      else if (typeof(T) == typeof(DateTime)) 
       return (dynamic)new DateTime((long)_value); 
      else 
       return (dynamic)_value; 
     } 
     set 
     { 
      if (typeof(T) == typeof(float)) 
       _value = (float)(object)value; 
      else if (typeof(T) == typeof(bool)) 
       _value = (bool)(object)value ? 1 : 0; 
      else if (typeof(T) == typeof(int)) 
       _value = (int)(object)value; 
      else if (typeof(T) == typeof(TimeSpan)) 
       _value = ((TimeSpan)(object)value).TotalSeconds; 
      else if (typeof(T) == typeof(DateTime)) 
       _value = ((DateTime)(object)value).Ticks; 
      else 
       _value = (double)(object)value; 
     } 
    } 
} 

class IntValue : BaseValue<int> 
{ 
    public IntValue() 
     : this(0, 0, string.Empty) 
    { } 

    public IntValue(int id, int value, string dimension) 
     : base(id, value, dimension) 
    { } 
} 

class BoolValue : BaseValue<bool> 
{ 
    public BoolValue() 
     : this(0, false, string.Empty) 
    { } 

    public BoolValue(int id, bool value, string dimension) 
     : base(id, value, dimension) 
    { } 
} 

class FloatValue : BaseValue<float> 
{ 
    public FloatValue() 
     : this(0, 0, string.Empty) 
    { } 

    public FloatValue(int id, float value, string dimension) 
     : base(id, value, dimension) 
    { } 
} 

class TimeSpanValue : BaseValue<TimeSpan> 
{ 
    public TimeSpanValue() 
     : this(0, TimeSpan.MinValue, string.Empty) 
    { } 

    public TimeSpanValue(int id, TimeSpan value, string dimension) 
     : base(id, value, dimension) 
    { } 
} 

class DateTimeValue : BaseValue<DateTime> 
{ 
    public DateTimeValue() 
     : this(0, DateTime.Now, string.Empty) 
    { } 

    public DateTimeValue(int id, DateTime value, string dimension) 
     : base(id, value, dimension) 
    { } 
} 

和庫從TPH表中選擇:

class Repository 
{ 
    public IEnumerable<BaseValue> GetAll() 
    { 
     IEnumerable<BaseValue> values = null; 

     using (SqlConnection cn = new SqlConnection("")) 
     { 
      cn.Open(); 

      const string query = "SELECT Id, TypeName, RawValue, Dimension FROM Values"; 

      values = cn.Query<BaseValue, object, BaseValue>(query, 
       (value, ignore) => 
       { 
        BaseValue child = null; 

        if (value.TypeName == "IntValue") 
         child = new IntValue(value.Id, (int)value.RawValue, value.Dimension); 
        else if (value.TypeName == "BoolValue") 
         child = new BoolValue(value.Id, value.RawValue > 0, value.Dimension); 
        else if (value.TypeName == "FloatValue") 
         child = new FloatValue(value.Id, (float)value.RawValue, value.Dimension); 
        else if (value.TypeName == "TimeSpanValue") 
         child = new TimeSpanValue(value.Id, TimeSpan.FromSeconds(value.RawValue), value.Dimension); 
        else if (value.TypeName == "DateTimeValue") 
         child = new DateTimeValue(value.Id, new DateTime((long)value.RawValue), value.Dimension); 

        return child; 
       }); 

      cn.Close(); 
     } 

     return values; 
    } 
}