嵌入式MongoDB文档在使用C#驱动程序保存时未获取ID

时间:2013-02-03 23:46:55

标签: c# mongodb mongodb-.net-driver

当我有一个包含文档列表的根文档并且我保存/插入时,根文档总是从MongoDB获取一个ID,但列表中的文档没有,它们与{{1}保持一致}。我不确定我做错了什么或者这是否是预期的行为?

这是我正在尝试做的一个例子: 鉴于课程:

ObjectId.Empty

有工厂:

public class Foo
{
    public ObjectId Id { get; set; }
    public string Name { get; set; }
    public IList<Bar> Bars { get; set; }
}

public class Bar
{
    public ObjectId Id { get; set; }
    public string Name { get; set; }
}

当我运行这样的样本时:

public class Factory
{
    public Foo CreateFoo(string name)
    {
        return new Foo {
            Id = new ObjectId(),
            Name = name,
            Bars = new List<Bar>()
        };
    }

    public Bar CreateBar(string name)
    {
        return new Bar {
            Id = new ObjectId(),
            Name = name
        };
    }
}

MongoDB生成的public class Program { static void Main(string[] args) { var client = new MongoClient("mongodb://localhost"); var server = client.GetServer(); var database = server.GetDatabase("Example1"); if (!database.CollectionExists("foos")) database.CreateCollection("foos"); var factory = new Factory(); var foo1 = factory.CreateFoo("first"); foo1.Bars.Add(factory.CreateBar("bar")); var collection = database.GetCollection("foos"); collection.Insert(foo1); var foo2 = factory.CreateFoo("second"); collection.Insert(foo2); foo2.Bars.Add(factory.CreateBar("bar")); collection.Save(foo2); } } foo1都得到了foo2,但_id都没有。所有Bars仍然拥有Bars。现在一个简单的解决方案是更新工厂以使用ObjectId.Empty,但我觉得从数据库生成它更舒服。有没有人对此有任何见解?难道我做错了什么?这甚至可能吗?感谢您的投入。

3 个答案:

答案 0 :(得分:1)

这是预期的行为。每个文档(不是子文档)都有一个_id,如果为空则自动分配。

您需要拥有单独的Bars集合并从Foo文档中引用它,或者手动生成ObjectIds。

如果您是从工厂[或存储库]进行的,那么它就会很稳固。

编辑:

另外,如果您使用

[BsonRepresentation(BsonType.ObjectId)]
string Id {get;set;}

这意味着您可以更轻松地访问objectId值,它仍然可以保存为ObjectId。

答案 1 :(得分:1)

当字段被标识为集合的_id时,驱动程序将仅为您生成Id字段。在您的情况下,Bar嵌入在Foo文档中。

因此,Bar拥有自动生成的Id字段是没有意义的。

在您的示例中,Bar没有理由拥有唯一的_id。查询集合时,您将根据_id的{​​{1}}进行查询,并在响应中提供Foo个对象。

这绝对是预期的行为。

答案 2 :(得分:0)

有一种常见方案可以更新或删除嵌入文档集合的一个元素。唯一的方法是依靠id。

目前我已经构建了一个自定义的IIdGenerator并将其分配给了IdMemberMap,但只调用了根文档。

是否有其他方法可以为嵌入文档生成自动ID?