Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何制作整数Id生成器?_C#_Mongodb - Fatal编程技术网

C# 如何制作整数Id生成器?

C# 如何制作整数Id生成器?,c#,mongodb,C#,Mongodb,众所周知,mongoDb默认驱动程序不支持自动生成整数Id。 我花了两天时间思考如何实现我自己的唯一整数值id生成器。 那么,如何制作呢?类似的东西: public class UniqueIntGenerator : IIdGenerator { private static UniqueIntGenerator _instance; public static UniqueIntGenerator Instance { get { return _instance; } }

众所周知,mongoDb默认驱动程序不支持自动生成整数Id。 我花了两天时间思考如何实现我自己的唯一整数值id生成器。 那么,如何制作呢?

类似的东西:

public class UniqueIntGenerator : IIdGenerator
{
    private static UniqueIntGenerator _instance;

    public static UniqueIntGenerator Instance { get { return _instance; } }

    static UniqueIntGenerator()
    {
        _instance = new UniqueIntGenerator();
    }

    public object GenerateId(object container, object document)
    {
        var cont = container as MongoCollection;
        if (cont == null)
            return 0;

        var type = cont.Settings.DefaultDocumentType;
        var cursor = cont.FindAllAs(type);
        cursor.SetSortOrder(SortBy.Descending("_id"));
        cursor.Limit = 1;

        foreach (var obj in cursor)
            return GetId(obj) + 1;

        return 1;
    }

    private int GetId(object obj)
    {
        var properties = obj.GetType().GetProperties();
        var idProperty = properties.Single(y => y.GetCustomAttributes(typeof(BsonIdAttribute), false).SingleOrDefault() != null);
        var idValue = (int)idProperty.GetValue(obj, null);
        return idValue;
    }

    public bool IsEmpty(object id)
    {
        return default(int) == (int)id;
    }
}

在MongoDB中生成自动增量Id不是一个好的做法,因为我会在扩展服务器时伤害到您,但是如果您想要生成自动增量值,则不建议迭代集合,而是创建一个单独的表(类似于序列的概念),从表中读取值,然后使用findAndModify对其进行增量。每个表都是唯一的

> db.counters.insert({_id: "userId", c: 0});

> var o = db.counters.findAndModify(
...        {query: {_id: "userId"}, update: {$inc: {c: 1}}});
{ "_id" : "userId", "c" : 0 }
> db.mycollection.insert({_id:o.c, stuff:"abc"});

> o = db.counters.findAndModify(
...        {query: {_id: "userId"}, update: {$inc: {c: 1}}});
{ "_id" : "userId", "c" : 1 }
> db.mycollection.insert({_id:o.c, stuff:"another one"});

我将使用GUID作为主键,而不是整数。 它主要有两个好处

  • 它是线程安全的
  • 您不必担心计算下一个ID
  • 获取新ID所需的代码非常简单

    Guid.NewGuid()


在CodingHorror中检查这个有用的选项,它解释了使用GUID而不是传统整数id的优缺点。

一个迟来的答案,但我想我会发布以下内容:

我启动了一个增量ID生成器。


注意——这远远不是理想的,也不是mongodb的初衷

如果不是必需的整数,您可能希望使用GUID作为快速解决方案…@cad:更好的快速解决方案是顺序整数:0,1,2,…不使用
http://www.mongodb.org/display/DOCS/Object+IDs
您是否看过关于customId generator的讨论
http://stackoverflow.com/questions/6855084/c-sharp-generate-identity-like-ids-with-nosql-mongodb
@vlad:不确定是否更好。顺序的重点是学习下一个数字。。。通常情况下,这不是线程安全的(可能使用单例可以使其安全),另一方面,GUID可能会有一些问题。如果您有时间查看codinghoror:@cad中的这篇很酷的文章:如果线程安全是一个问题,可以使用
锁来保护生成器。如果guid是线程安全的,它们也会这样做。我不熟悉MongoDb,但是:为什么总是将参数作为
对象
s进行转换?即使是线程安全的,它也不能与多个web服务器一起工作。@Vlad,因为IdGenerator对于许多集合都是通用的。所以方法GenerateId接受对象类型的参数。我发现没有办法获得find item的Id属性。这种方法存在大量并发问题。几乎同时插入的两个文档很容易具有相同的id,这可能会导致崩溃和数据损坏。但我不明白为什么使用另一个集合存储当前最大id不会影响服务器的扩展也是有害的,只是它比迭代整个集合更快更重要的是,此方法是原子的。对整个集合进行迭代是不正确的。这会影响扩展,因为现在需要两个服务器调用来插入记录(一个用于获取生成的ID,另一个用于插入记录)。但在一个典型的事务系统中,这一点并不多见。如果您有流式插入,比如日志记录或检测系统,那么这额外的开销可能会限制IO,尽管.MSSQL确实支持GUI。不使用GUID的一个重要原因是GUID通常是均匀分布的,这将导致使用b树的可怕的索引碎片。如果必须使用GUID,请确保使用具有顺序生成算法的GUID。ObjectID是按顺序生成的。如果不能直接使用Objd,请考虑使用Objutd的字符串形式。这至少不会导致索引碎片。@cad:而且,均匀分布的数据是最糟糕的事情,因为您需要调整磁盘上每个块的大小。对于磁盘上的数据结构,碎片是敌人。顺序ID(各种类型)更好,因为B-树只需要在末尾插入,而存储桶永远不需要拆分:它们可以被写入,直到填满为止,然后可以创建一个全新的存储桶并添加到树的末尾。GUID占用更多的磁盘空间(通过增加记录大小)和更多的搜索计算时间,比较和排序(有16个字节,而不是Int32的4个字节)。此外,顺序ID更易于人类查看、查询和理解:通过查看查询工具、Excel或类似工具中的数据,可以完成数量惊人的工作。大多数人可以立即发现5位或6位数字之间的差异,但是guid需要花费一些精力来处理。我们在工作中的一些表格中使用guid作为pk,它们让我发疯。