1

我正在尝试创建一个具有与下图类似的类和索引定义的索引:

public class Foo
{
    public string Tag { get; set; }
    public List<Bar> Bars { get; set; }
}

public abstract class Bar
{
    public int Weight { get; set; }
}

public class IronBar : Bar { }

public class ChocolateBar : Bar { }

public class TagSummary
{
    public string Tag { get; set; }
    public int Count { get; set; }
    public int TotalChocolateBarWeight { get; set; }
    public int TotalIronBarWeight { get; set; }
}

public class TagSummaryIndex : AbstractIndexCreationTask<Foo, TagSummary>
{
    public TagSummaryIndex()
    {
        Map = foos => from f in foos
                      select new
                      {
                          Tag = f.Tag,
                          Count = 1,
                          TotalChocolateBarWeight = f.Bars.OfType<ChocolateBar>().Sum(x=> x.Weight),
                          TotalIronBarWeight = f.Bars.OfType<IronBar>().Sum(x=> x.Weight)
                      };

        Reduce = results => from r in results
                            group r by r.Tag into g
                            select new
                            {
                                Tag = g.Key,
                                Count = g.Sum(x => x.Count),
                                TotalChocolateBarWeight = g.Sum(x => x.TotalChocolateBarWeight),
                                TotalIronBarWeight = g.Sum(x => x.TotalIronBarWeight)
                            };
    }
}

但是,当我尝试创建索引时

IndexCreation.CreateIndexes(this.GetType().Assembly, _documentStore);

它抛出一个 InvalidOperationException。如果我从中删除.OfType<T>()零件,Map 那么一切都很好(但不是我想要的)。我尝试过使用Where(x => x is ChocolateBar)和其他各种类型检查选项,但无济于事。

我将如何实现这一目标?

谢谢

4

1 回答 1

2

可能您可以做的最简单的事情是向您的类添加一些预先计算小计的属性。

public class Foo
{
    public string Tag { get; set; }
    public List<Bar> Bars { get; set; }
    public int ChocolateBarsWeight
    {
        get
        {
            return Bars.OfType<ChocolateBar>().Sum(x => x.Weight);
        }
    }
    public int IronBarsWeight
    {
        get
        {
            return Bars.OfType<IronBar>().Sum(x => x.Weight);
        }
    }
}

然后在索引图中使用这些值:

TotalChocolateBarWeight = f.ChocolateBarsWeight,
TotalIronBarWeight = f.IronBarsWeight

但是,我倾向于同意.OfType<T>()在这种情况下应该有效,但事实并非如此。原因是每个条的类型信息被序列化为$typejson 中的值。每当您存储抽象基类型或接口时,都会发生这种情况。例如:

{
    "Tag": "A",
    "Bars": [
        {
            "$type": "YourNameSpace.ChocolateBar, YourNameSpace",
            "Weight": 10
        },
        {
            "$type": "YourNameSpace.IronBar, YourNameSpace",
            "Weight": 1000
        }
    ]
}

乌鸦应该能够接受并妥善处理.OfType<T>()。我会在他们的下一个主要版本中推荐它。

于 2013-04-05T16:48:14.953 回答