C# RavenDb,查询类实现的属性
我有三个物体:汽车、汽车和摩托车。Vehicle是汽车和摩托车的抽象基类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};
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 });
}
}
}