.NET Core配置OData与Mongo时Id属性需为复杂属性报错如何解决
报错原因
- OData 约定模型构建器仅支持将.NET 内置基础类型(如 string、int、Guid、DateTime 等)作为实体主键类型,无法识别 MongoDB 专属的
ObjectId类型 - OData 会将无法识别的自定义值类型归类为复杂类型,而 OData 规范禁止将复杂类型设置为实体主键,因此在你将
Id声明为Item的主键时触发参数校验异常
修复方案
推荐使用兼容度更高的字符串Id映射方案,改动小且对前端调用更友好:
- 调整基类
Document的Id属性类型为string,同步修改CreatedAt的取值逻辑
public abstract class Document : IDocument { public string Id { get; set; } public DateTime CreatedAt => ObjectId.Parse(Id).CreationTime; }
- 在程序启动入口(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); });
- 原有OData配置无需任何改动,
string类型的Id可以被OData正常识别为主键。
如果你需要保留ObjectId类型的Id,可以采用第二种兼容方案:
- 在构建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(); }
- 配置JSON序列化规则,将
ObjectId序列化为字符串返回给前端:
services.AddControllers(options => { // 原有配置 }) .AddJsonOptions(options => { // 需引入MongoDB.Bson.Serialization.Converters命名空间 options.JsonSerializerOptions.Converters.Add(new ObjectIdJsonConverter()); }) .AddOData(opt => { // 原有OData配置 });
内容的提问来源于stack exchange,提问作者Gerald Hughes
相关产品推荐
相关产品推荐

