2011-12-05 13 views
2

私はDapper.netを使いたいと思っているので、私はそれを望んでいるようです:マッピング、私は何も想像する必要はありません、私はちょうど私のdatareaderと私の間のマッピングオブジェクト。継承とDapper.net

私の問題:

だが、私はこれらのクラスを持っているとしましょう:

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

そして、これらのテーブル:

Foo 
- ID 
- Name 

Bar 
- FooID 
- FavoriteMoovie 

だから私は、私は私はFooを選択することができますどのように知りたいと同じクエリ内のバー?

私の唯一のアイデアは、これまで

  • あるバー
  • ないすべてのFOOSを選択し、私はメソッドのオーバーロードを使用することはできませんすべてのバー

を選択「クエリなぜなら、ここでは関係をマッピングするためだけだからです。

+0

をこれはDapperについてのこと以外はhttp://stackoverflow.com/q/8344591/75642と同じ質問ではありませんか? –

+0

私が言ったように私の元の質問では、これはペタポコでは不可能なので、私はペタポコから外に出なければならなかった。私がここで言ったように、私はDapperのソリューションを持っていますが、このツールではより良いものを探しています –

答えて

1

非常にハッキーですが、これはおそらく動作します。

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を許可していない限り、これを処理するために2回だけクエリを実行することはありません。この場合、クエリを複雑にするか、2回選択するしかありません。場合

+0

これを処理する複数の選択を行いました。 "SELECT * INTO #temp FROM Foo; SELECT * FROM #temp where not exists (..)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; 
    } 
}