我有一个具有两个相似但不同的对象的应用程序,我想将这些对象存储在同一集合中。做这个的最好方式是什么?以及如何查询此收藏集?
今天,我的收藏集由
表示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更改为dynamic。但是当我这样做时,我无法查询集合。
答案 0 :(得分:1)
假设我将下一个conn连接到测试数据库:
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)]
装饰。希望对您有所帮助。
答案 1 :(得分:1)
在这种情况下,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
类,该类是动态的类字典结构,代表您的Mongo文档
var collection = db.GetCollection<BsonDocument>("posts");
更多详细信息here
将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
答案 2 :(得分:0)
使用 BsonDocument 数据类型。它可以做到这一切。 BsonDocument 和动态来回很方便。
public class CustomObject{
public long Id{get;set;}
public string Name{get;set;}
public List<(string,object)> CollectionDynamic{get;set;}
}
// inserted in mongo
//public class CustomObject_in_Db{
// public long Id {get;set;}
// public string Name {get;set;}
// public string field2 {get;set;}
// public string field3 {get;set;}
// public string field4 {get;set;}
// public string field5 {get;set;}
// }
// 一些代码... mapper(config)
Automapper.Mapper.CreateMap<BsonDocument,CustomObject>()
.ForMember(dest=>dest.Id, a=>a.MapFrom(s=>s.Id.GetValue(nameof(CustomObject.Id)).AsInt64)
.ForMember(dest=>dest.Name, a=>a.MapFrom(s=>s.Id.GetValue(nameof(CustomObject.Name)).AsString)
.ForMember(dest=>dest.CollectionDynamic, a=>a.MapFrom(s=>_getList(s));
// .......
private List<(string, object)> _getList(BsonDocument source){
return source.Elements.Where(e=>!typeof(CustomObject).GetProperties().Select(s=>s.Name).Any(a=>a ==e.Name)).Select(e=>e.Name, BsonTryMapper.MapToDotNetValue(e.Value)));
}