2014-04-30 49 views
1

我在同一个文档中有不同类型的通用对象:一个基础对象和两个具有不同属性的子对象。在数据库我只保留儿童,但最重要的是使用只有2个字段并缓存在内存中的基础对象。MongoDb C#只读字段

但有时我需要获取对象(儿童)的所有信息,而不仅仅是基础。为此,我需要知道儿童对象的类型(来自基础对象)。

要知道类型,MongoDb使用鉴别器。默认情况下它是_t。所以我决定把这个默认的鉴别添加到我的基类:

public string _t { get; private set; } 

现在我看到孩子的类型_t财产。所有工作正常保存在数据库对象,但不适用于新的objcets。 当我试图在db中保存一个新的childern对象时,它试图通过value = null传递那里的_t属性。但_t是用于鉴别器的保留字段,所以我收到错误:Duplicate element name '_t'

问题:

我怎么可能保持db对象模型_t属性,但本场仅适用于读操作映射?

解决方案: 这个问题实际上是只在新的对象,所以我做了这个:

[BsonIgnoreIfNull] 
public string _t { get; private set; } 

现在,如果_t是空的映射器会忽略这个属性,让MongoDB的驱动程序来创建一个鉴别器没有任何问题。

回答

2

你好像是re-inventing the wheel这里。要么使用内置鉴别器(它会自动序列化一个_t字段),或者使用write your own serializer

[BsonDiscriminator("Base")] 
[BsonKnownTypes(typeof(D1), ...)] 
class Base { 
} 
class D1 : Base { 
} 

那些将被序列化自动(无需在_t自己添加)作为

{ "_id" : 1, "_t" : "Base", ... } 
分别

{ "_id" : 1, "_t" : "D1", ... } 

当您将字段_t添加到您的类本身时,您正在“侵入”默认序列化程序的保留空间。另外,从OOP的角度来看,将类的名称存储在对象实例中似乎没有多大意义,所以最好避免这种情况。

使用自定义序列化程序,您可能可以避免为基类的实例编写鉴别符值,但我认为这不值得麻烦。

+0

在,我不想在数据库中手动保存对象类型。 _t是一个标准的鉴别器,可以自动保存在数据库中,我不想改变这种行为。我只想读_t。我不想将它保存在数据库中。那就是问题所在。 我会看看自定义串行器。 任何方式感谢您的帮助! – Max

+0

好的,在这种情况下,只需读取类“T {public string _t {get; set;}}'或'BsonDocument'类型的对象。这样,默认的串行器将不会调用鉴别器。 – mnemosyn

+0

这就是我所做的。这适用于已经保存在数据库中的旧对象,并具有_t。但对于新的对象,它试图保存默认鉴别字段_t。该操作返回错误:重复的元素名称'_t'。这很明显。我无法设置保留字段来保存操作。所以我需要以某种方式告诉映射器/序列化器不映射/序列化_t保存操作,只为读取...谢谢! – Max