为什么 AsQueryable 不意味着对_t鉴别器进行过滤

本文关键字:鉴别 过滤 AsQueryable 意味着 为什么 | 更新日期: 2023-09-27 18:32:11

假设模型

[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof (Dog), typeof (Cat))]
class Animal
{
    public ObjectId Id {get;set;}
    public string Name {get;set;}
}
class Dog : Animal { public int BarkVolume {get;set;} }
class Cat : Animal { public int PurrVolume {get;set;} }

我可以执行以下操作:

var collection = new MongoClient().GetServer().GetDatabase("test").GetCollection<Animal("Animals");
collection.Save( new Dog { Name="spot", BarkVolume=7 } );
collection.Save( new Cat { Name="kitty", PurrVolume=2 } );

但是,如果我然后尝试只查询

var cats = collection.AsQueryable<Cat>();
foreach(var c in cats)
{
   Console.WriteLine("{0} purrs at {1}", c.Name, c.PurrVolume);
}

我会得到一个异常"元素BarkVolume与类Cat的任何字段或属性不匹配"。

当然,如果我将查询更改为: var cats = collection.AsQueryable<Cat>().Where(x=>x is Cat);

那么没问题,但是有一个警告,说明 x 是 Cat 总是正确的。

驱动程序没有在鉴别器上注入测试是否有特殊原因_t

为什么 AsQueryable<T> 不意味着对_t鉴别器进行过滤

这是一个设计决策(在工作了一段时间后,我同意)。要指定_t过滤器,您可以使用比x => x is Cat更干净的OfType扩展方法。

在MongoDB C#驱动程序中,几乎所有内容都有类型化和非类型化选项。键入的选项只是为了舒适起见,它们不会更改生成的查询。当您真正关心查询性能和索引利用率时,这是一件好事。

例如,如果您使用仅特定类型具有的属性进行查询,则无需添加OfType(以及生成的_t筛选器),并且如果您这样做,查询引擎可能会使用您可能不希望它执行的_t索引。