【问题标题】:MongoDB C# Driver - Return an Id of type string from controllerMongoDB C# 驱动程序 - 从控制器返回字符串类型的 Id
【发布时间】:2015-02-14 01:21:21
【问题描述】:

我有以下型号:

public class Student
{
    public ObjectId Id { get; set; }
    public string Name { get; set; }
}

我的控制器中的这个端点:

public IEnumerable<Student> GetAll()
{
    MongoCollection<Student> collection = Db.GetCollection<Student>("students");
    List<Student> students = collection.AsQueryable().ToList();
    return students;
} 

向公众公开的 GetAll() 端点返回一个具有 ObjectId 类型的 Id 的 Student,它不是标准类型。我宁愿希望它是字符串类型。

但如果我将其更改为字符串,我将无法使用 .ToList(),出现如下错误:
"Cannot deserialize string from BsonType ObjectId"

我知道我可以使用一些投影和转换来解决这个问题,但是它们会给 CRUD 方法添加一些丑陋和嘈杂的代码。

保持字符串类型中的Id向公众公开并且仍然能够使用c#驱动程序的api的最佳方法是什么?

【问题讨论】:

  • 如果要使用字符串而不是ObjectId,也需要直接在Mongo中将类型从ObjectId更改为String。如果您浏览数据,例如使用 MongoVue,您会看到数据类型是 ObjectId。 Id 可以是任何东西(甚至是复杂的对象),但您需要在 DB 和类定义中具有相同的类型。
  • @Pierre-LucPineault:我不敢苟同。您可以注册自定义序列化程序,这很常见。此外,C# 驱动程序带有用于大量类型的内置序列化程序,其中许多类型是 mongo 未知的,包括 decimalStackDictionaryIPAddress 甚至 CultureInfo,请参阅 github.com/mongodb/mongo-csharp-driver/tree/master/src/…在数据库中使用字符串影响性能和存储

标签: c# mongodb


【解决方案1】:

控制器应该进行转换。通常,控制器应该使用 DTO 与外界进行通信:

public IEnumerable<StudentReadDTO> GetAll()
{
    MongoCollection<Student> collection = Db.GetCollection<Student>("students");
    List<Student> students = collection.AsQueryable().ToList();
    return students.Select(p => AutoMapper.Mapper.DynamicMap<StudentReadDTO>(p));
} 

// this DTO should be used for POST and PUT (i.e where there is no id or the id 
// is part of the URL) - after all, it doesn't make sense to send the id from the
// client to the server
public class StudentDTO
{
    public string Name { get; set; }
}

// this should be used by reading operations, where the id is read from the server
// inheritance in DTOs is a source of confusion and can be painful, but this trivial
// type of inheritance will be fine
public class StudentReadDTO : StudentDTO
{
    public string Id { get; set; }
}

此示例使用AutoMapperStudentStudentDTO 之间进行基于约定的映射,但如果您愿意,您可以自己进行映射。

在数据库层,使用ObjectId是有意义的,因为its properties.

【讨论】:

  • 我将如何回答 :)
  • AutoMapper 是否知道如何自动将字符串转换为 ObjectId,反之亦然?此外,这些转换(使用或不使用 AutoMapper)是否会对性能产生影响? (此控制器将用于具有密集读/写操作的环境)
  • 是的,它会的,因为它会自动找到匹配的构造函数。不过,您可以根据需要自定义转换。 AutoMapper 文档非常好。在 RAM 中将几个字节从一种表示映射到另一种表示应该在商品硬件的 3 位数纳秒范围内。与访问网络堆栈(以毫秒为单位)相比,这算不了什么。
【解决方案2】:

虽然@mnemosyn 使用 AutoMapper 建议的答案看起来是一个很好的解决方案和一个很好的模式来处理这些情况,但对于 MongoDB C# 驱动程序,你有一个专用的解决方案,可以简单地放置以下属性,你完成:

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

    public string Name { get; set; }
} 

(我从MongoDB的google group得到这个解决方案)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多