MongoDb自定义集合序列化器 [英] MongoDb custom collection serializer
问题描述
我有四个简单的课程
public class Zoo{
public ObjectId Id { get; set; }
public List<Animal> Animals { get; set; }
}
public class Animal{
public ObjectId Id { get; set; }
public string Name { get; set; }
}
public class Tiger : Animal{
public double Height { get; set; }
}
public class Zebra : Animal{
public long StripesAmount { get; set; }
}
我创建了自定义序列化程序,该序列化程序使我可以将Animal对象存储在不同的集合(动物")中.
I have created the custom serializer which allows me to store Animal object in a distinct collection ("animals").
class MyAnimalSerializer : SerializerBase<Animal>
{
public override void Serialize(MongoDB.Bson.Serialization.BsonSerializationContext context, MongoDB.Bson.Serialization.BsonSerializationArgs args, Animal value)
{
context.Writer.WriteStartDocument();
context.Writer.WriteName("_id");
context.Writer.WriteObjectId(ObjectId.GenerateNewId());
context.Writer.WriteName("_t");
context.Writer.WriteString(value.GetType().Name);
context.Writer.WriteName("Name");
context.Writer.WriteString(value.Name);
switch (value.AnimalType)
{
case AnimalType.Tiger:
context.Writer.WriteName("Height");
context.Writer.WriteDouble((value as Tiger).Height);
break;
case AnimalType.Zebra:
context.Writer.WriteName("StripesAmount");
context.Writer.WriteInt32((value as Zebra).StripesAmount);
break;
default:
break;
}
context.Writer.WriteEndDocument();
}
public override Animal Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args)
{
context.Reader.ReadStartDocument();
ObjectId id = context.Reader.ReadObjectId();
string object_type = context.Reader.ReadString();
string animal_name = context.Reader.ReadString();
switch (object_type)
{
case "Tiger":
double tiger_height = context.Reader.ReadDouble();
context.Reader.ReadEndDocument();
return new Tiger()
{
Id = id,
Name = animal_name,
Height = tiger_height
};
default:
long zebra_stripes = context.Reader.ReadInt64();
context.Reader.ReadEndDocument();
return new Zebra()
{
Id = id,
Name = animal_name,
StripesAmount = zebra_stripes
};
}
return null;
}
}
哪个效果很好,还允许我执行以下操作:
Which works well and also allows me things like that:
MongoDB.Bson.Serialization.BsonSerializer.RegisterSerializer(typeof(Animal), new MyAnimalSerializer());
IMongoCollection<Animal> collection = db.GetCollection<Animal>("animals");
var lst = await collection.Find<Animal>(new BsonDocument()).ToListAsync();
但是当动物存储在动物园中时,我不能做同样的事情 并且无法从Zoo集合反序列化Zoo:
But I cannot do the same, when Animals are stored in Zoo and cannot deserialize Zoo from Zoo collection:
IMongoCollection<Zoo> collection = db.GetCollection<Zoo>("zoocollection");
var lst = await collection.Find<Zoo>(new BsonDocument()).ToListAsync(); //not working here
是否可以为该字段创建自定义集合序列化程序?
public List<Animal> Animals { get; set; }
有人可以举一个例子吗? 提前致谢.
Could anyone give an example? Thanks in advance.
推荐答案
Have you visited this document page? There are also examples for polymorphic classes.
这是我存储对象的示例:
Here is my example of storing objects:
public class Zoo
{
[BsonId]
public ObjectId Id { get; set; }
public List<Animal> Animals { get; set; }
}
[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(Tiger), typeof(Zebra))]
public class Animal
{
[BsonId]
public ObjectId Id { get; set; }
public string Name { get; set; }
}
public class Tiger : Animal
{
public double Height { get; set; }
}
public class Zebra : Animal
{
public long StripesAmount { get; set; }
}
public class MongoDocumentsDatabase
{
/// <summary>
/// MongoDB Server
/// </summary>
private readonly MongoClient _client;
/// <summary>
/// Name of database
/// </summary>
private readonly string _databaseName;
public MongoUrl MongoUrl { get; private set; }
/// <summary>
/// Opens connection to MongoDB Server
/// </summary>
public MongoDocumentsDatabase(String connectionString)
{
MongoUrl = MongoUrl.Create(connectionString);
_databaseName = MongoUrl.DatabaseName;
_client = new MongoClient(connectionString);
}
/// <summary>
/// Get database
/// </summary>
public IMongoDatabase Database
{
get { return _client.GetDatabase(_databaseName); }
}
public IMongoCollection<Zoo> Zoo { get { return Database.GetCollection<Zoo>("zoo"); } }
}
class Program
{
static void Main(string[] args)
{
var connectionString =
"mongodb://admin:admin@localhost:27017/testDatabase";
var pr = new Program();
pr.Save(connectionString);
var zoo = pr.Get(connectionString);
foreach (var animal in zoo.Animals)
{
Console.WriteLine(animal.Name + " " + animal.GetType());
}
}
public void Save(string connectionString)
{
var zoo = new Zoo
{
Animals = new List<Animal>
{
new Tiger
{
Height = 1,
Name = "Tiger1"
},
new Zebra
{
Name = "Zebra1",
StripesAmount = 100
}
}
};
var database = new MongoDocumentsDatabase(connectionString);
database.Zoo.InsertOneAsync(zoo).Wait();
}
public Zoo Get(string connectionString)
{
var database = new MongoDocumentsDatabase(connectionString);
var task = database.Zoo.Find(e => true).SingleAsync();
task.Wait();
return task.Result;
}
}
以下是对象在数据库中的存储方式(Robomongo)
Here is how objects were stored in database (Robomongo)
最终结果:
这篇关于MongoDb自定义集合序列化器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!