Коллекция Mongodb как динамическая - PullRequest
1 голос
/ 28 марта 2019

У меня есть приложение, в котором есть два похожих, но разных объекта, и я хочу сохранить эти объекты в одной коллекции. Каков наилучший способ сделать это? И как я могу запросить эту коллекцию?

Сегодня мои коллекции представлены:

public IMongoCollection<Post> Posts
{
    get
    {
        return _database.GetCollection<Post>("posts");
    }
}

И у меня есть этот класс:

public class Post
{
    public string Id { get; set; }
    public string Message { get; set; }
}

public class NewTypePost
{
    public string Id { get; set; }
    public string Image { get; set; }
}

Итак, сегодня я могу просто сохранять и запрашивать, используя класс Post. Теперь я хочу сохранить и извлечь оба класса, Post и NewTypePost.

Я пытался изменить тип класса с Post на динамический. Но когда я сделал это, я не смог запросить коллекции.

Ответы [ 2 ]

1 голос
/ 28 марта 2019

Драйвер MongoDB .NET предлагает несколько вариантов в таких случаях:

Полиморфизм

Вы можете построить иерархию классов, и драйвер MongoDB сможет определить тип объекта, который он получает из базы данных:

[BsonKnownTypes(typeof(Post), typeof(NewTypePost))]
public abstract class PostBase
{
    [BsonId]
    public string Id { get; set; }
}


public class Post: PostBase
{        
    public string Message { get; set; }
}

public class NewTypePost: PostBase
{
    public string Image { get; set; }
}

Драйвер MongoDB создаст дополнительное поле _t в каждом документе, которое будет представлять соответствующий класс.

Одноместный класс

Вы по-прежнему можете иметь класс Post и использовать атрибут BsonIgnoreIfNull, чтобы избежать исключения сериализации. Драйвер MongoDB .NET установит эти свойства на null, если они не существуют в вашей базе данных.

public class Post
{   
    [BsonId]
    public string Id { get; set; }
    [BsonIgnoreIfNull]     
    public string Message { get; set; } 
    [BsonIgnoreIfNull]
    public string Image { get; set; }
}

BsonDocument

Вы также можете отказаться от строго типизированного подхода и использовать BsonDocument класс, который представляет собой динамическую словарную структуру, представляющую ваши монго-документы

var collection = db.GetCollection<BsonDocument>("posts");

Подробнее здесь

динамический

Указав dynamic в качестве общего параметра ICollection, вы должны получить список ExpandoObject , в котором будут храниться все значения, имеющиеся в вашей базе данных.

var collection = db.GetCollection<dynamic>("posts");
var data = collection.Find(Builders<dynamic>.Filter.Empty).ToList();
var firstMessage = data[0].Message; // dynamically typed code
1 голос
/ 28 марта 2019

Предположим, у меня есть следующее соединение с тестовой базой данных:

var mongoClient = new MongoClient(new MongoClientSettings
{
    Server = new MongoServerAddress("localhost"),
});
var database = mongoClient.GetDatabase("TestDb");

Тогда я могу сделать что-то вроде:

var col = database.GetCollection<Post>("posts");
var col2 = database.GetCollection<NewTypePost>("posts");

Чтобы получить два разных экземпляра IMongoCollection, но указывающих на одну и ту же коллекцию в базе данных. Далее я могу сохранить в каждую коллекцию обычным способом:

col.InsertOne(new Post { Message = "m1" });
col2.InsertOne(new NewTypePost { Image = "im1" });

Затем я также могу запросить базу данных этих полей по определенным полям:

var p1= col.Find(Builders<Post>.Filter.Eq(x=>x.Message, "m1")).FirstOrDefault();
var p2 =col2.Find(Builders<NewTypePost>.Filter.Eq(x=>x.Image, "im1")).FirstOrDefault();

Console.WriteLine(p1?.Message); // m1
Console.WriteLine(p2?.Image);  // im1

Я не знаю, хотите ли вы этого, но он использует ту же коллекцию. Кстати, измените свойства Id, чтобы они были украшены [BsonId, BsonRepresentation(BsonType.ObjectId)]. Надеюсь, это поможет.

...