MongoDb自定义集合序列化器 [英] MongoDb custom collection serializer

查看:148
本文介绍了MongoDb自定义集合序列化器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有四个简单的课程

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆