继承和Dapper.net

3

我决定使用Dapper.net,因为它似乎只做我想要的事情:映射,我不需要任何花哨的东西,我只是厌倦了处理数据读取器和对象之间的映射。

我的问题是:

假设我有这些类:

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

并且这些表格:

Foo 
- ID
- Name

Bar
- FooID
- FavoriteMoovie

我想知道如何在同一个查询中选择我的Foo和Bars?

目前我唯一的想法是:

  • 选择所有不是Bars的Foos
  • 然后选择所有的Bars

我不能使用方法“Query”的重载,因为它们只是用于映射关系。


这不是与http://stackoverflow.com/q/8344591/75642相同的问题吗,只不过它是关于Dapper的吗? - Robert Koritnik
正如我在之前的问题中所说,我不得不放弃Petapoco,因为它无法实现这个功能。就像我在这里所说的那样,我已经找到了使用Dapper的解决方案,但我正在寻找更好的工具来完成此任务。 - remi bourgarel
2个回答

2
非常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,否则不要查询两次来处理此问题,因为这样会使查询变得复杂,或者只能选择两次。

我使用多项选择来处理这个问题:“SELECT * INTO #temp FROM Foo; SELECT * FROM #temp WHERE NOT EXISTS(...)SELECT * FROM #temp INNER JOIN bar ON...” - remi bourgarel
我认为这应该是 bar.FavoriteMoovie != null - sharno

1
在每个层次结构TPH中使用一个表时,很容易获取所有具体的子类Class,特别是当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 表中选择并存储到 Repository 中:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接