You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core配置OData与Mongo时Id属性需为复杂属性报错如何解决

报错原因
  • OData 约定模型构建器仅支持将.NET 内置基础类型(如 string、int、Guid、DateTime 等)作为实体主键类型,无法识别 MongoDB 专属的 ObjectId 类型
  • OData 会将无法识别的自定义值类型归类为复杂类型,而 OData 规范禁止将复杂类型设置为实体主键,因此在你将 Id 声明为Item的主键时触发参数校验异常
修复方案

推荐使用兼容度更高的字符串Id映射方案,改动小且对前端调用更友好:

  1. 调整基类Document的Id属性类型为string,同步修改CreatedAt的取值逻辑
public abstract class Document : IDocument
{
    public string Id { get; set; }
    public DateTime CreatedAt => ObjectId.Parse(Id).CreationTime;
}
  1. 在程序启动入口(Program.cs)配置 MongoDB 序列化规则,实现存储时自动将string类型Id转换为MongoDB原生ObjectId,读取时自动转回string:
// 需引入MongoDB.Bson.Serialization、MongoDB.Bson.Serialization.IdGenerators、MongoDB.Bson.Serialization.Serializers命名空间
BsonClassMap.RegisterClassMap<Document>(cm =>
{
    cm.AutoMap();
    cm.MapIdMember(c => c.Id)
      .SetSerializer(new StringSerializer(BsonType.ObjectId))
      .SetIdGenerator(StringObjectIdGenerator.Instance);
});
  1. 原有OData配置无需任何改动,string类型的Id可以被OData正常识别为主键。

如果你需要保留ObjectId类型的Id,可以采用第二种兼容方案:

  1. 在构建Edm模型时手动将ObjectId注册为OData支持的原始类型:
public static IEdmModel GetEdmModel()
{
    var builder = new ODataConventionModelBuilder();
    // 注册ObjectId为OData原始类型
    builder.AddPrimitiveType(typeof(ObjectId));
    
    var entitySetConfiguration = builder.EntitySet<Item>("Item");
    entitySetConfiguration.EntityType.HasKey(entity => entity.Id);
    return builder.GetEdmModel();
}
  1. 配置JSON序列化规则,将ObjectId序列化为字符串返回给前端:
services.AddControllers(options =>
{
    // 原有配置
})
.AddJsonOptions(options =>
{
    // 需引入MongoDB.Bson.Serialization.Converters命名空间
    options.JsonSerializerOptions.Converters.Add(new ObjectIdJsonConverter());
})
.AddOData(opt =>
{
    // 原有OData配置
});

内容的提问来源于stack exchange,提问作者Gerald Hughes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 21:24:04