不使用JsonProperty属性,如何更改保存在Cosmos DB中的属性名称?

4

我需要更改保存在Cosmos Db中的属性名称。我不想使用Newtonsoft.Json的JsonProperty属性,因为使用它会导致始终更改属性的名称,甚至在调用操作方法时也是如此。因此,我希望仅在保存到Cosmos Db中的JSON具有不同的属性名称。为此,我创建了一个名为CosmosDbPropertyAttribute的自定义属性,如下所示:

[AttributeUsage(AttributeTargets.Property)]
public class CosmosDbPropertyAttribute : Attribute
{
    public string PropertyName { get; set; }

    public CosmosDbPropertyAttribute(string propertyName)
    {
        PropertyName = propertyName;
    }
}

以下是使用 CosmosDbProperty 属性的示例类:
```csharp public class Item { public string Id { get; set; }
[CosmosDbProperty(PropertyName = "item_name")] public string Name { get; set; }
[CosmosDbProperty(PropertyName = "item_quantity")] public int Quantity { get; set; } } ```
在这个示例中,我们定义了一个名为 Item 的类,并且使用 CosmosDbProperty 属性来设置其属性名称。这样,在将对象存储到 Cosmos DB 中时,该属性将被序列化为指定的名称而不是默认的属性名称。
public abstract class CosmosDbDocumentBase : ICosmosDbDocument
{
    [CosmosDbProperty("CID")]
    public virtual string CustomerId { get; set; }

    [CosmosDbProperty("DT")]
    public virtual int DocumentType { get; set; }

    [CosmosDbProperty("id")]
    public string Id { get; set; }

    [CosmosDbProperty("PK")]
    public string PartitionKey { get; set; }
}

在序列化过程中一切都很顺利,因为我已经在DocumentClient对象的JsonSerializerSettings中使用自定义的ContractResolver覆盖了CreateProperty方法。

public class CosmosDbDefaultContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty jsonProperty = base.CreateProperty(member, memberSerialization);
        if (member.GetCustomAttributes(typeof(CosmosDbPropertyAttribute)).FirstOrDefault() is CosmosDbPropertyAttribute PropertyAttribute)
        {
            jsonProperty.PropertyName = PropertyAttribute.PropertyName;
            return jsonProperty;
        }
        else
        {
            return jsonProperty;
        }
    }
}

问题现在出现在查询数据库上。当我像这样进行LINQ查询时:
var _DbClient = new DocumentClient(new Uri("_DB URI_"), "_DB KEY_", new JsonSerializerSettings()
{
    ContractResolver = new CosmosDbDefaultContractResolver()
}, connectionPolicy);

var Query = _DbClient.CreateDocumentQuery<T>().Where(a => a.DocumentType == 0).AsEnumerable();

查询语句有误,因为它引用了原始属性名DocumentType而不是在CosmosDbProperty属性中指定的DT,导致查询失败。
1个回答

1

我会采取不同的方法来解决这个问题。我会实现一个仓库模式,该模式暴露与所需类相对应的API,但将属性映射到内部DB模型类。

即,我会使用下面返回或由仓库消费的类。

public class CosmosDbDocumentBase
{

    public virtual string CustomerId { get; set; }
    public virtual int DocumentType { get; set; }
    public string Id { get; set; }
    public string PartitionKey { get; set; }
}

但我也会有一个内部的数据库模型:

class CosmosDbModel
{
    public virtual string CID { get; set; }
    public virtual int DT { get; set; }
    public string id { get; set; }
    public string PK { get; set; }
}

你可以使用Automapper来双向映射字段(或手动映射),映射逻辑可以在所有存储库方法中共享。这将避免所有不必要的复杂注释,并考虑到你确实需要JSON表示和单独的DB表示,两个单独的类将提供必要的关注点分离。

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