Reputation: 2488
When I have a root document that has a list of documents and I save/insert, the root document always gets an ID from MongoDB, but the documents in the list don't, they remain the same as ObjectId.Empty
. I'm not sure if I'm doing something wrong or if this is intended behavior?
Here's an example of what I'm trying to do: Given the classes:
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; }
}
With a Factory:
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
};
}
}
When I run a sample like this:
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);
}
}
Both foo1
and foo2
get _id
's generated by MongoDB, but none of the Bars
do. All the Bars
still have the ObjectId.Empty
. Now an easy solution is to update the factory to use ObjectId.GenerateNewId()
, but I'd feel more comfortable with it being generated from the DB. Does anyone have any insight on this? Am I doing something wrong? Is this even possible? Thanks for the input.
Upvotes: 4
Views: 4364
Reputation:
There is one frequent scenario to update or remove one element of the embeded document collection. The only way is to rely on the id.
At the moment I have built a customised IIdGenerator and have assigned it to the IdMemberMap, but it only gets called for the root document.
Is there any other way to generate automatic ids for embeded documents?
Upvotes: 0
Reputation: 13463
The driver will only generate the Id field for you when the fields is identified as the _id
of a collection. In your case, Bar
is embedded inside the Foo
document.
Therefore, it doesn't make sense for Bar
to have an auto-generated Id field.
In your example, there is really no reason for Bar
to have a unique _id
. When you query the collection, you will query based on the _id
of Foo
and you'll have Bar
objects available in the response.
This is definitely intended behavior.
Upvotes: 1
Reputation: 6813
It's intended behaviour. Each document (not sub-document) has an _id which get assigned automatically if empty.
You either need to have a separate collection of Bars and reference it from the Foo documents, or manually generate the ObjectIds.
If you're doing it from a factory [ or repository ] then it would be solid.
EDIT:
Also, if you use
[BsonRepresentation(BsonType.ObjectId)]
string Id {get;set;}
It means you can access the objectId value more easily, it would still be saved of ObjectId.
Upvotes: 1