MongoDB ObjectIds曝光

时间:2014-09-19 14:46:28

标签: c# mongodb

我有一个数据层(包含与MongoDB的连接),一个域层(包含repos和实体)和一个服务层(包含服务和模型)

现在因为我的实体使用了ObjectIds,它们需要了解MongoDB(这很好吗?)

我的服务调用返回这些实体的存储库,然后将它们转换为模型。这导致我的服务层需要知道MongoDB,因为实体上有ObjectId属性。

有没有办法可以避免这种情况?我听说我可以使用我的Id作为类型字符串,当存储数据时,MongoDB会将其转换为ObjectId吗?

2 个答案:

答案 0 :(得分:3)

简短版本:是的,在任何地方使用字符串。

如果您对注释没问题,请使用:

[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }

否则你可以使用类映射:

BsonClassMap.RegisterClassMap<i_YourModel>(cm =>
 {
  cm.AutoMap();
  cm.SetIdMember(cm.GetMemberMap(x => x.Id)
    .SetIdGenerator(StringObjectIdGenerator.Instance));
 }
);

长版:

建议尽可能在模型和服务层中使用不透明的东西(不直接连接到底层数据库实现)(如果可能)。

以前,主键ID通常是大数字,然后映射到数据库上的数字主键列。但是,在为新实体分配新ID时,必须对数据库进行检查以确保具有唯一ID。存在许多技术,从LO-HI id生成器到auto_increment列,再到序列等。

使用NoSQL,并且需要更多的并行性,大多数应用程序现在使用UUID或其变体,因为ID可以以合理的概率生成,它将是唯一的,而不必询问数据库是否真的是唯一的,或者使用序列等,这是在水平扩展的应用程序中的瓶颈。

MongoDB没有区别,并且使用的是一种UUID的ObjectId。

这些id(mongo和其他)总是可以表示为字符串,通常是组成键的字节的HEX表示。因此,在您的模型中使用String as id,在您的服务层中,在您的数据层中将其转换为适合您的底层数据库实现的任何格式,在这种情况下为MongoDB。

答案 1 :(得分:1)

有时仅映射Id可能会令人困惑,以及在同一实体中可能有另一个objectId(可能是引用)的情况下会发生什么?

您可以使用地图convention over configuration模式为objectId制作地图。看看下面的实现:

public static class MongoDbConventionRegistry
{
    public static void Register()
    {
        var conventionPack = new ConventionPack {new StringObjectIdMemberMapConvention()};            
        ConventionRegistry.Register("CustomConventions", conventionPack, t => t.FullName.StartsWith("YourNamespace.Model.Entities.etc")); 
     }

 }

public class StringObjectIdMemberMapConvention : IMemberMapConvention
{
    private  readonly Regex _memberMatchRegex = new Regex(@"(^Id$)|(.+ObjectId?$)",RegexOptions.Compiled); // you can change this regex to match the convention you want

    public string Name {
            get { return "StringObjectId"; }
        }

        public void Apply(BsonMemberMap memberMap)
        {
            if (memberMap == null)
                return;
            if(memberMap.MemberType == typeof(string) && _memberMatchRegex.IsMatch(memberMap.ElementName) )
                memberMap.SetRepresentation(BsonType.ObjectId);
        }

    }

因此,对于这种情况,任何以objectId结尾的Id和任何其他属性都将映射到objectId,因此您可以将实体ID保留为字符串,驱动程序将为您处理转换,它更方便您不希望在系统中的大多数图层之间携带mongodb依赖项。

您可以将约定更改为您想要的任何内容,我只想高亮显示该功能。