C#+ MongoDB-不使用MongoDB数据类型/属性的ObjectId [英] C# + MongoDB - ObjectId without using MongoDB DataTypes/Attributes
问题描述
使用MongoDB作为我的数据存储,默认情况下使我具有ObjectID类型作为主键.也可以通过将Guid与[BsonId]属性一起使用来更改它. MongoDB C#驱动程序库中也定义了该库.我想让我的实体独立于数据层. 我可以仅使用属性的名称ID来标识主键吗?我还能尝试什么?
Using MongoDB as my data store makes me to have ObjectID type as primary key by Default. It also can be changed by using Guid with [BsonId] attribute. Which is also defined in MongoDB C# Driver library. I would like to have my Entities independent from Data layer. Can I just use name Id for the property to identify primary key? What else I can try?
推荐答案
选项1:坚持使用BsonId并使用外观模式
[BsonId]属性是用于指示_id属性应链接到特定属性的属性.没有办法解决这个问题(在您的操作中完全忽略_id似乎是个坏主意).
OPTION 1: Stick with BsonId and use the Facade Pattern
The [BsonId] property is what you'd use to indicate that the _id property should be linked to a specific property. There isn't a way around that (short of ignoring _id entirely in your crud operations which seems like a bad idea).
因此,如果要将实体"对象与数据层"分开,则只需使用poco类.
So, if you want to separate your "entity" object from your "data layer" then just use a poco class.
-- Use a poco class as a substitute for a record. That class is only for data storage: a quick way to get data in/out of mongo, and a great alternative to working with bson documents.
-在该poco类的顶部为您的实体层使用外观.我认为重新发明轮子没什么用,所以我通常会问我们的开发人员让实体接口继承数据层(poco)接口,但是您可以根据自己的意愿做
-- Use a facade on top of that poco class for your entity layer. I don't find it useful to re-invent the wheel, so I typically ask our devs have the entity interface inherit the data-layer (poco) interface, but you can do it however you'd like
IMyObjectRecord (在dal声明,仅包含属性和mongo特定的属性)
IMyObjectRecord (declared at the dal and contains only properties and mongo-specific attributes)
IMyObject:IMyObjectRecord (在实体级别声明,可能包括添加的属性和方法)
IMyObject:IMyObjectRecord (declared at the entity level and may include added properties and methods)
MyObjectRecord:IMyObjectRecord (在dal内声明,包含mongo特定的属性.如果您想严格限制分隔,可以声明为内部).
MyObjectRecord:IMyObjectRecord (declared inside the dal, contains mongo-specific attributes. Could be declared internal if you wanted to be really strict about separation).
MyObject:IMyObject (例如,可以是从dal拉出的IMyObjectRecord类顶部的外观).
MyObject:IMyObject (could be, for example, a facade on top of the IMyObjectRecord class you pull from the dal).
现在-您可以获得外观的所有优点,并且在属性BUT之间具有硬编码链接,可以将dalson属性保留在dal中.
Now - you get all the benefits of the facade, and you have a hard-coded link between the properties BUT, you get to keep Bson attributes contained in your dal.
是的.我可以接受. 好,那么约定包怎么样?:如果您完全承诺将您的ID称为"Id",并且发誓要将其键入为字符串(或者-使用其他一些约定,很容易识别),那么我们可以使用约定包像我从这里偷来的包
Yeah. I can accept that. OK, so how about a Convention Pack? If you ABSOLUTELY PROMISE that you'll call your Id's "Id" and you SWEAR that you'll type them as strings (or -- use some other convention that is easy to identify), then we could just use a convention pack like the one I stole from here
namespace ConsoleApp {
class Program {
private class Foo {
// Look Ma! No attributes!
public string Id { get; set; }
public string OtherProperty { get; set; }
}
static void Main(string[] args) {
//you would typically do this in the singleton routine you use
//to create your dbClient, so you only do it the one time.
var pack = new ConventionPack();
pack.Add(new StringObjectIdConvention());
ConventionRegistry.Register("MyConventions", pack, _ => true);
// Note that we registered that before creating our client...
var client = new MongoClient();
//now, use that client to create collections
var testDb = client.GetDatabase("test");
var fooCol = testDb.GetCollection<Foo>("foo");
fooCol.InsertOne(new Foo() { OtherProperty = "Testing", Id="TEST" });
var foundFoo = fooCol.Find(x => x.OtherProperty == "Testing").ToList()[0];
Console.WriteLine("foundFooId: " + foundFoo.Id);
}
//obviously, this belongs in that singleton namespace where
//you're getting your db client.
private class StringObjectIdConvention : ConventionBase, IPostProcessingConvention {
public void PostProcess(BsonClassMap classMap) {
var idMap = classMap.IdMemberMap;
if (idMap != null && idMap.MemberName == "Id" && idMap.MemberType == typeof(string)) {
idMap.SetIdGenerator(new StringObjectIdGenerator());
}
}
}
}
}
什么是公约包
这是在序列化/反序列化过程中应用的少量mongo规则".您只需注册一次(设置引擎时).在这种情况下,示例包告诉mongo如果您看到一个名为'Id'的字段,请将该字段另存为_id."
What's a Convention Pack
It's a little set of mongo "rules" that get applied during serialize/deserialize. You register it once (when you setup your engine). In this case, the sample pack is telling mongo "if you see a field called 'Id', then save it as a string to _id, please."
这些会变得非常复杂和有趣.如果您真的非常讨厌其他方法,那么我将深入探讨惯例包.这是将所有mongo属性驱动"逻辑强制到一个独立位置的好方法.
These can get really complex and fun. I'd dig into convention packs if you really really really hate the other approach. It's a good way to force all your mongo "attribute driven" logic into one self-contained location.
这篇关于C#+ MongoDB-不使用MongoDB数据类型/属性的ObjectId的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!