Cosmos DB Newtonsoft反序列化问题

时间:2018-09-06 18:01:04

标签: c# json.net azure-cosmosdb

我在CosmosDb中遇到一个奇怪的问题,无法反序列化我的课程。

我得到的错误是

  

无法创建类型为TestApp.Entities.IVisitItem的实例。类型是   接口或抽象类,无法实例化

启动类中有以下代码

 JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
        {
            TypeNameHandling = TypeNameHandling.Auto
        };

当我在数据浏览器中查看文档时,我可以看到类型信息已正确保存

  "VisitItems": [
            {
                "$type": "TestApp.Entities.NoteVisitItem, TestApp.Entities",
                "Note": "fsfsdfdsfsdf",
                "VisitId": "22931c75-efb4-59ea-5b1b-7533bd8bb570",
                "VisitItemType": "Note",
                "Created": "0001-01-01T00:00:00",
                "CreatedById": null,
                "CreatedByName": null,
                "Id": "1e6233cf-e970-4b9f-b60b-a8fb62c94c81"
            }
        ]

如果有人可以阐明我需要做些什么才能正确反序列化,将不胜感激。

顺便说一句,这是一个使用Microsoft.Azure.DocumentDB / 2.0.0-preview2的.net核心2.1项目。

我在所有项目上都使用NewtonsoftJson 11.0.2,它看起来与DocumentDB库所使用的版本相同。

更新-这是我的数据访问代码

  public class CosmosDocumentDbClient : IDbClient
{
    private readonly ConcurrentDictionary<string,Uri> _collectionLinks = new ConcurrentDictionary<string, Uri>();
    private readonly IList<IDisposable> _disposables = new List<IDisposable>();
    private DocumentClient _client;
    private string _databaseId;

    public CosmosDocumentDbClient(IConfigurationRegister configurationRegister)
    {
        var subscription = configurationRegister.Configuration<CosmosDbConfiguration>().Subscribe(c =>
        {
            this._databaseId = c.DatabaseId;
            this._client = new DocumentClient(new Uri(c.EndpointUri), c.Key);

            this.InitialiseDb(this._client, c.DatabaseId, "Case", "Owner").Wait();
        });

        _disposables.Add(subscription);
    }

    public async Task Initialise()
    {
    }

    public IQueryable<TEntity> GetCollection<TEntity>()
    {
        return this._client.CreateDocumentQuery<TEntity>(GetCollectionLink(typeof(TEntity).Name));
    }

    public async Task<List<TEntity>> ToListAsync<TEntity>(Func<IQueryable<TEntity>, IQueryable<TEntity>> items)
    {
        return  await items.Invoke(
            this._client.CreateDocumentQuery<TEntity>(GetCollectionLink(typeof(TEntity).Name)))
            .ToListAsync();
    }

    public async Task<TEntity> FirstOrDefaultAsync<TEntity>(IQueryable<TEntity> query)
    {
        return (await query.Take(1).ToListAsync()).FirstOrDefault();
    }

    public async Task<TEntity> Get<TEntity>(string id)
    {           
       var docUri = UriFactory.CreateDocumentUri(_databaseId, typeof(TEntity).Name,id);
       return await _client.ReadDocumentAsync<TEntity>(docUri);
    }

    public async Task Insert<TEntity>(TEntity entity) where TEntity : IEntity
    {
        await _client.UpsertDocumentAsync(GetCollectionLink(typeof(TEntity).Name), entity);
    }

    public  async Task Update<TEntity>(TEntity entity) where TEntity : IEntity
    {
        try
        {
            var docUri = UriFactory.CreateDocumentUri(_databaseId, typeof(TEntity).Name,entity.Id);
            await _client.ReplaceDocumentAsync(docUri, entity);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }

    }

    private async Task InitialiseDb(DocumentClient client, string databaseId, params string[] collectionIds)
    {
        await client.CreateDatabaseIfNotExistsAsync(new Database() {Id = databaseId});

        foreach (var collectionId in collectionIds)
        {
            await client.CreateDocumentCollectionIfNotExistsAsync(
                UriFactory.CreateDatabaseUri(databaseId), new DocumentCollection {Id = collectionId});
        }
    }

    private Uri GetCollectionLink(string collectionName)
    {
        if (!_collectionLinks.ContainsKey(collectionName))
        {
            _collectionLinks.TryAdd(collectionName,
                UriFactory.CreateDocumentCollectionUri(_databaseId, collectionName));
        }
        return _collectionLinks[collectionName];
    }

1 个答案:

答案 0 :(得分:2)

所以,正如我们通过评论所总结的。

CosmosDB的DocumentClient有自己的JsonSerialiser设置对象,您需要在其中配置TypeNameHandling设置。

仅将其设置为JsonConvert.DefaultSettings级别将使其可以在序列化上使用,但在反序列化期间将失败。

DocumentClient级添加它可以解决此问题。