我有一个 .NET Core 3.1 API 项目,其中通过实体框架 (Microsoft.EntityFrameworkCore.Cosmos - v3.1.5) 处理 Cosmos DB 存储。
我有一个数据库模型:
[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class BikeRental
{
[JsonProperty(PropertyName = "id")]
[Key]
public Guid Id { get; set; }
[JsonProperty(PropertyName = "bikeId")]
public string BikeId { get; set; }
[JsonProperty(PropertyName = "shopId")]
public string ShopId { get; set; }
}
保存到 CosmosDB 数据库后,将使用类属性名称对列进行序列化,忽略“PropertyName”属性。例如,如果“bikeId”更改为“testBikeId”,则仍写为“BikeId”。
{
"Id": "192dfdf4-54cb-4290-a478-7035518983ca",
"BikeId": "eb65b93b-17d3-4829-9729-d48c029211fe2",
"ShopId": "636c08c4-600d-458a-98b7-8d312b8c18d2",
"_rid": "2QZIAMVYbVQBAAAAAAAAAA==",
"_self": "dbs/2QZIAA==/colls/2QZIAMVYbVQ=/docs/2QZIAMVYbVQBAAAAAAAAAA==/",
"_etag": "\"00000000-0000-0000-4627-f721b0e701d6\"",
"_attachments": "attachments/",
"_ts": 1592564051
}
任何有关如何解决此问题的帮助或建议将不胜感激!
编辑: 将对象保存到 Cosmos 是通过以下方式执行的:
var response = _context.BikeRentals.Add(obj)
_context.SaveChanges();
在
OnModelCreating
方法中使用Fluent API进行模型配置:
modelBuilder.Entity<BikeRental>().Property(x => x.Id).ToJsonProperty("id");
modelBuilder.Entity<BikeRental>().Property(x => x.BikeId).ToJsonProperty("bikeId");
modelBuilder.Entity<BikeRental>().Property(x => x.ShopId).ToJsonProperty("shopId");
对于 EF 映射,使用 ColumnAttribute 或使用 OnModelCreating 中的流畅配置。
对于 Cosmos,您可能希望数据库中的名称与序列化发送到客户端时的名称相同,但在一般情况下,您的实体映射到数据库的方式可能与 JSON 序列化不同。
您应该使用 Fluent API 并迭代所有实体类型和属性并应用 Pascal-to-Camel-Case 转换。
我想出了一个扩展方法来处理这个问题
public static void CamelCasePropertyNames<T>(this EntityTypeBuilder<T> entity)
where T : class
{
foreach (var property in typeof(T).GetProperties())
{
entity.Property(property.Name)
.ToJsonProperty(char.ToLowerInvariant(property.Name[0]) + property.Name.Substring(1));
}
}
编辑:遇到集合类型失败的问题,因为这与 OwnsMany 冲突,使用以下内容过滤属性修复了此问题
.Where(p => p.PropertyType.IsGenericType is false)
我用小写字母制作了我的属性,属性约定不是今天! 通过提供的解决方案(例如属性(newtonsoft vs System.Text)/API 流畅)节省了很多痛苦(如果你有很多属性,你真的会映射它们中的每一个吗?嵌套类又如何?)
id的问题是因为没有添加
modelBuilder.Entity<BikeRental>().HasNoDiscriminator();
如果你添加这个,它应该只创建 id