C# RavenDb,查询类实现的属性

C# RavenDb,查询类实现的属性,c#,ravendb,nosql,C#,Ravendb,Nosql,我有三个物体:汽车、汽车和摩托车。Vehicle是汽车和摩托车的抽象基类 public abstract class Vehicle { public String Color {get;set}; public Int Price {get;set}; public DateTime ReleaseDate {get;set}; } public class Car : Vehicle { public Int EnginePower {get;set};

我有三个物体:汽车、汽车和摩托车。Vehicle是汽车和摩托车的抽象基类

public abstract class Vehicle
{
    public String Color {get;set};
    public Int Price {get;set};
    public DateTime ReleaseDate {get;set};
}

public class Car : Vehicle
{
    public Int EnginePower {get;set};
    public Int TrunkSpace {get;set};
    public bool GearBoxType {get;set};
    public Int Seats {get;set};
}

public class MotorCycle : Vehicle
{
    public Int EnginePower {get;set};
    public String Type{get;set};
}
我想把所有的汽车,摩托车。。。在RavenDb的同一个文档集合中。所以我使用这个约定,它是有效的:

documentStore.Conventions.FindTypeTagName =
   type => type.IsSubclassOf(typeof(Vehicle)) ?
       DocumentConvention.DefaultTypeTagName(typeof(Vehicle)) :
       DocumentConvention.DefaultTypeTagName(type);
现在我想为所有车辆的请求做索引。但我想询问车辆属性和汽车、摩托车属性

请举例说明我将:

颜色=红色,发动机功率>100的所有车辆 颜色=红色、发动机功率>100、座椅=5的所有车辆 所有类型为滑板车的车辆 等 结果只有一个车辆类型集合,order by RealeaseDate。
如何在C和linq中执行类似的查询?

RavenDB将实体保存为其派生类型,并基于这些类型构建任何自动索引

您需要做的是创建一个新的索引,对基类中所有不同类型的属性进行索引,然后从该索引中进行选择

public class VehicleIndex : AbstractMultiMapIndexCreationTask
{
public VehicleIndex()
{
 this.AddMap<Car>(vehicle => from v in vehicle select new { v.Price , v.Color , v.ReleaseDate });
 this.AddMap<Motorcycle>(vehicle => from v in vehicle select new { v.Price , v.Color , v.ReleaseDate });
}
}
我已经写了一篇关于使用接口的更深入的博客文章,但同样的技术也适用于抽象基类。看


实际上,这是一种非常强大的技术,允许您充分利用Raven的无模式特性。

我遇到了这条线索,希望更正目前在这里发布的评论/答案

可以创建所有继承的索引

一般来说,最好将所有继承保存在单独的集合中。所以,换言之,不要把汽车作为瑞文的交通工具,而是作为汽车

然后,您可以使用MultiMapIndex查询不同继承之间的相似性,但也可以保留为特定继承创建单独索引的选项(如果需要)

要获得所需的结果,只需将结果另存为一个新类型,其中包含所有要索引的属性,甚至基于子类的输入创建新属性

public class VehicleIndex : AbstractMultiMapIndexCreationTask
{
    public class Mapping
    {
        public string Price { get; set; }
        public string Color { get; set; }
        public string ReleaseDate { get; set; }
        public int?  EnginePower { get; set;}
    }

    public VehicleIndex()
    {
        this.AddMap<Car>(vehicle => from v in vehicle select new Mapping()
        {
            Price = v.Price,
            Color = v.Color,
            ReleaseDate = v.ReleaseDate,
            EnginePower = v.EnginePower
        });
        this.AddMap<Motorcycle>(vehicle => from v in vehicle select new Mapping()
        {
            Price = v.Price,
            Color = v.Color,
            ReleaseDate = v.ReleaseDate,
            EnginePower = v.EnginePower
        });
    }
}

请注意,如果您想按EnginePower进行查询,您需要将属性移动到基类并将其包含在索引中。感谢您的回复,但我不想移动EnginePower属性。我可以在我的单个文档集合和多个类型中从RavendbStudio查询子类属性。在C语言中是不可能做到这一点的,那么您需要使用一个接口并根据它构建索引。在RavenDB中要记住的是,一切都是一个索引,你永远不会像查询数据库一样真正地查询它。创建包含抽象类实现的所有属性的索引的唯一解决方案是什么?摩托车和汽车的特性?因此,这些属性通常为空。。。
public void AddMapForPolymorphic<TBase>(Expression<Func<IEnumerable<TBase>, IEnumerable>> expr)
    {
        AddMap(expr);
        var children = Modules.Modules.Instance.GetModules()
            .SelectMany(a => AssemblyHelper.GetClassesWithBaseType<TBase>(a.GetType().Assembly)
            );

        var addMapGeneric = GetType()
            .GetMethod("AddMap", BindingFlags.Instance | BindingFlags.NonPublic);

        foreach (var child in children)
        {
            if (!child.HasAttribute<IgnorePolymorpAttribute>())
            {
                var genericEnumerable = typeof(IEnumerable<>)
                    .MakeGenericType(child);

                var delegateType = typeof(Func<,>)
                    .MakeGenericType(genericEnumerable, typeof(IEnumerable));

                var lambdaExpression = Expression.Lambda(delegateType, expr.Body, Expression
                    .Parameter(genericEnumerable, expr.Parameters[0].Name));

                addMapGeneric
                    .MakeGenericMethod(child).Invoke(this, new[] { lambdaExpression });
            }
        }
    }