Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.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#类层次结构的MongoDb顺序整数id生成器_C#_Mongodb_Id Generation - Fatal编程技术网

用于C#类层次结构的MongoDb顺序整数id生成器

用于C#类层次结构的MongoDb顺序整数id生成器,c#,mongodb,id-generation,C#,Mongodb,Id Generation,我有一个C#类层次结构,带有分离的BsonClass映射。我的所有类都使用自定义的顺序int-id生成。存储在名为“计数器”的特殊集合中的最后一个Id。我的问题是当mongo收集方法(如InsertOneAsync)被调用为InvalidCastException时抛出 基本实体类: [Serializable] public abstract class Entity<TIdentifier> : IEntity<TIdentifier> { public TI

我有一个C#类层次结构,带有分离的BsonClass映射。我的所有类都使用自定义的顺序int-id生成。存储在名为“计数器”的特殊集合中的最后一个Id。我的问题是当mongo收集方法(如InsertOneAsync)被调用为InvalidCastException时抛出

基本实体类:

[Serializable]
public abstract class Entity<TIdentifier> : IEntity<TIdentifier>
{
    public TIdentifier Id { get; set; }

    public DateTime CreatedDate { get; set; }

    public DateTime UpdatedDate { get; set; }

    public virtual bool IsTransient()
    {
        return (object) this.Id == null || this.Id.Equals((object) default (TIdentifier));
    }
}
[可序列化]
公共抽象类实体:通用性
{
公共TIdentifier Id{get;set;}
公共日期时间CreatedDate{get;set;}
公共日期时间更新日期{get;set;}
公共虚拟boolistransient()
{
返回(object)this.Id==null | | this.Id.Equals((object)default(TIdentifier));
}
}
儿童班:

public class Child : Entity<int> 
{
    public int SomeData { get; set; }
}
公共类子类:实体
{
公共int SomeData{get;set;}
}
基类映射:

public class EntityMap
{
    public static void Register()
    {
        BsonClassMap.RegisterClassMap<Entity<int>>(cm =>
        {
            cm.AutoMap();
            cm.MapIdProperty(c => c.Id)
                .SetIdGenerator(SeqIntIdGenerator<Entity<int>>.Instance)
                .SetSerializer(new Int32Serializer(BsonType.Int32));
        });
    }
}
public class ChildMap
{
    public static void Register()
    {
        BsonClassMap.RegisterClassMap<Child>(cm =>
        {
            cm.AutoMap();
            cm.SetIgnoreExtraElements(true);
        });
    }
}
公共类EntityMap
{
公共静态无效寄存器()
{
BsonClassMap.RegisterClassMap(cm=>
{
cm.AutoMap();
cm.MapIdProperty(c=>c.Id)
.SetIdGenerator(seqintidgeGenerator.Instance)
.SetSerializer(新的Int32Serializer(BsonType.Int32));
});
}
}
子类映射:

public class EntityMap
{
    public static void Register()
    {
        BsonClassMap.RegisterClassMap<Entity<int>>(cm =>
        {
            cm.AutoMap();
            cm.MapIdProperty(c => c.Id)
                .SetIdGenerator(SeqIntIdGenerator<Entity<int>>.Instance)
                .SetSerializer(new Int32Serializer(BsonType.Int32));
        });
    }
}
public class ChildMap
{
    public static void Register()
    {
        BsonClassMap.RegisterClassMap<Child>(cm =>
        {
            cm.AutoMap();
            cm.SetIgnoreExtraElements(true);
        });
    }
}
公共类ChildMap
{
公共静态无效寄存器()
{
BsonClassMap.RegisterClassMap(cm=>
{
cm.AutoMap();
cm.SetIgnoreExtraElements(真);
});
}
}
顺序int id生成器类:

public class SeqIntIdGenerator<TEntity> : IIdGenerator
{
    public static SeqIntIdGenerator<TEntity> Instance { get; } = new SeqIntIdGenerator<TEntity>();

    public object GenerateId(object container, object document)
    {
        //InvalidCastException thrown here on InsertOneAsync!!!
        var idSequenceCollection = ((IMongoCollection<TEntity>)container).Database.GetCollection<dynamic>("Counters");

        var filter = Builders<dynamic>.Filter.Eq("_id", ((IMongoCollection<TEntity>)container).CollectionNamespace.CollectionName);
        var update = Builders<dynamic>.Update.Inc("Seq", 1);

        var options = new FindOneAndUpdateOptions<dynamic>
        {
            IsUpsert = true,
            ReturnDocument = ReturnDocument.After
        };

        return idSequenceCollection.FindOneAndUpdate(filter, update, options).Seq;
    }

    public bool IsEmpty(object id)
    {
        return (int)id == 0;
    }
}
public类seqinitedgenerator:IIdGenerator
{
公共静态SekinTidgeGenerator实例{get;}=new SekinTidgeGenerator();
公共对象生成器ID(对象容器、对象文档)
{
//InvalidCastException在InsertOneAsync上抛出!!!
var idSequenceCollection=((IMongoCollection)container.Database.GetCollection(“计数器”);
var filter=Builders.filter.Eq(“_id”,((IMongoCollection)容器).CollectionNamespace.CollectionName);
var update=Builders.update.Inc(“Seq”,1);
var options=new FindOneAndUpdateOptions
{
IsUpsert=true,
ReturnDocument=ReturnDocument.After
};
返回idSequenceCollection.FindOneAndUpdate(筛选器、更新、选项)。Seq;
}
公共布尔值为空(对象id)
{
返回(int)id==0;
}
}

将容器从对象强制转换到IMongoCollection>时引发InvalidCastException。如何做对?我的C#驱动程序版本是2.7.2。

好的,这是我使用反射的丑陋解决方案

public class SeqIntIdGenerator<TEntity> : IIdGenerator
{
    var containerType = container.GetType();
    var database = (IMongoDatabase)containerType.GetProperty("Database").GetValue(container);
    var collectionNamespace = (CollectionNamespace)containerType.GetProperty("CollectionNamespace").GetValue(container);

    var idSequenceCollection = database.GetCollection<dynamic>("Counters");

    var filter = Builders<dynamic>.Filter.Eq("_id", collectionNamespace.CollectionName);
    var update = Builders<dynamic>.Update.Inc("Seq", 1);

    var options = new FindOneAndUpdateOptions<dynamic>
    {
        IsUpsert = true,
        ReturnDocument = ReturnDocument.After
    };

    return idSequenceCollection.FindOneAndUpdate(filter, update, options).Seq;
    }

    public bool IsEmpty(object id)
    {
        return (int)id == 0;
    }
}
public类seqinitedgenerator:IIdGenerator
{
var containerType=container.GetType();
var database=(IMongoDatabase)containerType.GetProperty(“数据库”).GetValue(容器);
var collectionNamespace=(collectionNamespace)containerType.GetProperty(“collectionNamespace”).GetValue(容器);
var idSequenceCollection=database.GetCollection(“计数器”);
var filter=Builders.filter.Eq(“\u id”,collectionNamespace.CollectionName);
var update=Builders.update.Inc(“Seq”,1);
var options=new FindOneAndUpdateOptions
{
IsUpsert=true,
ReturnDocument=ReturnDocument.After
};
返回idSequenceCollection.FindOneAndUpdate(筛选器、更新、选项)。Seq;
}
公共布尔值为空(对象id)
{
返回(int)id==0;
}
}

如果您已经在使用dynamic,您可以为此切换反射代码>

public object GenerateId(object container, object document)
{
    var containerDynamic = (dynamic) container;
    var idSequenceCollection = containerDynamic.Database.GetCollection<dynamic>("Counters");

    var filter = Builders<dynamic>.Filter.Eq("_id", containerDynamic.CollectionNamespace.CollectionName);
    var update = Builders<dynamic>.Update.Inc("Seq", 1);

    var options = new FindOneAndUpdateOptions<dynamic>
    {
        IsUpsert = true,
        ReturnDocument = ReturnDocument.After
    };

    return idSequenceCollection.FindOneAndUpdate(filter, update, options).Seq;
}
public object GenerateId(对象容器、对象文档)
{
var containerDynamic=(动态)容器;
var idSequenceCollection=containerDynamic.Database.GetCollection(“计数器”);
var filter=Builders.filter.Eq(“\u id”,containerDynamic.CollectionNamespace.CollectionName);
var update=Builders.update.Inc(“Seq”,1);
var options=new FindOneAndUpdateOptions
{
IsUpsert=true,
ReturnDocument=ReturnDocument.After
};
返回idSequenceCollection.FindOneAndUpdate(筛选器、更新、选项)。Seq;
}

谢谢您的回答,但假设我们有许多从实体派生的子类。您的解决方案是什么样的?尝试将容器强制转换到每个IMongoCollection并不是最好的解决方案。这就是我为什么写“足够了”。如果我想到使用
TEntity
作为基本泛型类型,我将修改代码@АаааааСаааааСаааааа1072。