Azure Cosmos DB(EF/Core) - 驼峰命名属性名

7
我有一个.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();

你是如何进行序列化的? - Vivek Nuna
序列化是由Entity Framework执行的。因此,当将对象添加到相关上下文时,就会发生这种情况。我已经编辑了原始帖子以包含此信息。 - Mike
4个回答

4

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");

1
我想到了一个扩展方法来处理这个问题。
    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)

0

对于 EF 映射,请使用 ColumnAttribute 或在 OnModelCreating 中使用流畅配置。

在 Cosmos 的情况下,您可能希望数据库中的名称与序列化发送到客户端时的名称相同,但是在一般情况下,实体可能会以与 JSON 序列化不同的方式映射到数据库中。

您应该使用 Fluent API 并迭代所有实体类型和属性,然后应用 Pascal-to-Camel-Case 转换。


1
谢谢David。在OnModelCreating中添加转换已经起作用了。 - Mike
2
David,抱歉再次打扰您。虽然我现在已经按照您的建议成功解决了这个问题,但我又遇到了另一个问题。将属性声明为Id后,它会被正确映射到“id”。但是,由于某种原因,Cosmos会将类类型添加到ID中?例如:“id”:“BikeRental | 01f7be19-4f0f-44d1-9fa9-721195cf2d45”, - Mike
ColumnAttribute 在 EF Core 6 中似乎不起作用,我也没有在任何文档中看到它,但使用流畅的配置非常好 - 只是要打更多的字。 ;) - dsghi
我认为ColumnAttributes不起作用的原因是因为Dotnet Core中的属性被映射到json中的属性,而不是列。但是我同意Cosmosdb应该有一个替代的属性。 - Junaid

-1

id的问题是由于没有添加而引起的

  modelBuilder.Entity<BikeRental>().HasNoDiscriminator();

如果您添加此内容,它应该只创建ID。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接