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