我为我的游戏提供了REST服务,并决定尝试使用MongoDB - 除了“_id”字段要求外,似乎非常简单。
这里的问题是我的客户端应用程序正在使用REST服务,并且不了解“mongodb”,它的驱动程序或依赖项 - 也不应该。为了将客户端与服务器端(REST服务提供者)分离,我需要解决MongoDB似乎需要BsonObjectId类型的“_id”字段这一事实。
目前我正在使用轻量级DAO层,因此不需要:
using System;
public class Item {
private BsonObjectId _id;
private string name;
}
我正在使用DAO将其转换为“mongodb agnostic”:
using System;
public class ItemDAO {
private string _id;
private string name;
}
理想情况下完全摆脱BsonObjectId会很好 - 是否有一些注释/自定义序列化处理程序可以使用或者某种方式我可以使用字符串而不是BsonObjectId?
如果失败了,任何方法都可以获取MongoDB包装的对象,以便用_id修饰它们,我可以将它作为字符串注入行中?
理想的结果是根本没有DAO类只是“Item”,而且Item使用_id的字符串(或者不需要mongodb依赖的东西来流入客户端实现)。
答案 0 :(得分:2)
您的文档必须包含_id字段,但它不必是ObjectID。唯一的要求是它对于该系列来说是独一无二的。
如果您在保存新文档时没有提供_id字段,MongoDB会为您生成一个ObjectId,但这只是一个辅助函数。
答案 1 :(得分:2)
如果你不想" polute"您的模型条款,您可以在数据访问代码中注册适当的Id生成器。
BsonSerializer.RegisterIdGenerator(typeof(string), new StringObjectIdGenerator());
这样你的模型中就会有String字段,但是它下面会是ObjectId,这很好看,即你可以看到添加的记录(大约)
如果您决定在REST服务中接受来自客户端的ID(通过PUT),那么ObjectId显然不是可行的方法。
看一下这个article,因为它描述了如何设置序列化选项等。
答案 2 :(得分:0)
如何查询对象?如果您不希望/需要客户端中的_id字段,则可以使用projection从结果中排除_id字段。
另外,请注意,生成自己的基于字符串的_id会对数据库大小产生严重影响。 ObjectId似乎是一个非常有效的结构。我已经尝试过为_id使用字符串,以避免在我永远不会使用的字段上有索引 - 但在我的情况下,数据库大小的成本使它变得不可行。当然,取决于您的数据库大小和其他内容。
答案 3 :(得分:0)
将BSON ObjectIds表示为字符串是常见的;默认情况下,Mongo驱动程序将生成96位ID,然后您可以将其显示为24个十六进制字节。大多数客户端库都具有从字符串中创建ObjectId
并将其转换为字符串的功能。
您可以让外部接口将_id
视为字符串,然后当您的Mongo感知数据库层以字符串形式接收_id时,它只会在内部将其转换为ObjectId.from_string(_id)
或诸如此类的东西。在编写结果时,您只需将OID转换为字符串。
答案 4 :(得分:0)
使用ObjectIds作为主键的数据类型对various reasons很有意义。生成具有低碰撞概率的良好,非连续,单调的ID并不是微不足道的,并且重新发明轮子或基本上重写该特征并不值得。
数据映射应该在 controllers 中完成,它们应该使用DTO与外部交互。换句话说,当您的数据库使用数据库模型时,您的REST端点(控制器/模块)应该是已知的DTO。
DTO看起来与您的模型非常相似,但它们可能会少一些字段(如果您不希望通过API公开内部数据,那么它们很整洁)并且它们使用模型中的字符串使用ObjectIds。
为避免愚蠢的复制代码,请使用类似AutoMapper的内容。