Наследование и Dapper.net - PullRequest
       2

Наследование и Dapper.net

3 голосов
/ 05 декабря 2011

Я решил использовать Dapper.net, потому что он, кажется, делает только то, что я хочу: отображение, мне не нужно ничего необычного, мне просто скучно обрабатывать отображение между моим устройством чтения данных и моим объектом.

Моя проблема:

Допустим, у меня есть эти классы:

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

И эти таблицы:

Foo 
- ID
- Name

Bar
- FooID
- FavoriteMoovie

Итак, я хотел бы знать, как я могу выбрать свои Foo и Bars в одном запросе?

Моя единственная идея на данный момент это

  • ВЫБЕРИТЕ все Foos, которые не являются барами
  • затем ВЫБЕРИТЕ все бары

Я не могу использовать перегрузку метода «Запрос», потому что здесь есть только для отображения отношений.

Ответы [ 2 ]

2 голосов
/ 18 декабря 2011

Очень хакерский, но это, вероятно, работает.

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, и в этом случае у вас нет выбора, кроме как усложнить запрос или выбрать дважды.

1 голос
/ 23 августа 2016

в случае, когда по одной таблице на иерархию TPH легко получить все конкретные дочерние классы, особенно если базовый класс является абстрактным

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