mongoDB:C# 驱动程序 V2 如何更新嵌套集合中的项目 [英] mongoDB: C# driver V2 How to update item in a nested collection

查看:63
本文介绍了mongoDB:C# 驱动程序 V2 如何更新嵌套集合中的项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下类设计:

public class UserDayStore
{
    public Guid Id { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public DateTime EndOfSubscription { get; set; }
    public bool active { get; internal set; }
    public DateTime LastModified;

    public List<DbDayRecord>  Days { get; set; }
}

public class DbDayRecord
{
    public Guid StoreId { get; set; }
    public DateTime LastModified { get; set; }
    public DateTime DateOfDay { get; set; }

    public String Quote { get; set; }

}

添加 UserDayStore 没有问题,也可以向 List 添加嵌套项.当我尝试更新 DayRecord 时,更新已完成,就像我在 Robomongo 中看到的那样.但是当我尝试在 UserStore 集合中搜索此之后的文档时,我得到了这个异常:

Adding a UserDayStore works without a problem, also Adding a nested Item to List<Days> is ok. When I try to update a DayRecord, the Update is done as I can see in Robomongo. But when I try to search for a document after this in the UserStore collection I get this Exception:

System.FormatException

System.FormatException

反序列化类的 Days 属性时出错QuoteMyDayServer.ServerLogic.UserDayStore:无法反序列化来自 BsonType 'Document' 的 'List'.

An error occurred while deserializing the Days property of class QuoteMyDayServer.ServerLogic.UserDayStore: Cannot deserialize a 'List' from BsonType 'Document'.

bei MongoDB.Driver.Linq.MongoQueryProviderImpl1.Execute(Expression表达) beiMongoDB.Driver.Linq.MongoQueryProviderImpl1.Execute[TResult](表达式表达式) bei System.Linq.Queryable.First[TSource](IQueryable1来源) beiQuoteMyDayServer.ServerLogic.QuoteDatabase.d__10.MoveNext()在C:\Entwicklung\Apps\QuoteMyDay\Server\QuoteMyDayServer\QuoteMyDayServer\ServerLogic\QuoteDatabase.cs:Zeile147.--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- beiSystem.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)贝System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务task) bei System.Runtime.CompilerServices.TaskAwaiter1.GetResult()在 NancyTests.MongoTests.d__8.MoveNext() 中C:\Entwicklung\Apps\QuoteMyDay\Server\QuoteMyDayServer\NancyTests\MongoTests.cs:Zeile148.--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- beiSystem.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)贝System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)贝Xunit.Sdk.TestInvoker`1.<>c__DisplayClass46_1.<b__1>d.MoveNext()在C:\BuildAgent\work\cb37e9acf085d108\src\xunit.execution\Sdk\Frameworks\Runners\TestInvoker.cs:Zeile227.--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- beiSystem.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)贝System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) bei Xunit.Sdk.ExecutionTimer.d__4.MoveNext()在C:\BuildAgent\work\cb37e9acf085d108\src\xunit.execution\Sdk\Frameworks\ExecutionTimer.cs:Zeile48.--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- beiSystem.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)贝System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) bei Xunit.Sdk.ExceptionAggregator.d__9.MoveNext()在C:\BuildAgent\work\cb37e9acf085d108\src\xunit.core\Sdk\ExceptionAggregator.cs:Zeile90.

bei MongoDB.Driver.Linq.MongoQueryProviderImpl1.Execute(Expression expression) bei MongoDB.Driver.Linq.MongoQueryProviderImpl1.Execute[TResult](Expression expression) bei System.Linq.Queryable.First[TSource](IQueryable1 source) bei QuoteMyDayServer.ServerLogic.QuoteDatabase.<SetUserState>d__10.MoveNext() in C:\Entwicklung\Apps\QuoteMyDay\Server\QuoteMyDayServer\QuoteMyDayServer\ServerLogic\QuoteDatabase.cs:Zeile 147. --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) bei System.Runtime.CompilerServices.TaskAwaiter1.GetResult() bei NancyTests.MongoTests.d__8.MoveNext() in C:\Entwicklung\Apps\QuoteMyDay\Server\QuoteMyDayServer\NancyTests\MongoTests.cs:Zeile 148. --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) bei Xunit.Sdk.TestInvoker`1.<>c__DisplayClass46_1.<b__1>d.MoveNext() in C:\BuildAgent\work\cb37e9acf085d108\src\xunit.execution\Sdk\Frameworks\Runners\TestInvoker.cs:Zeile 227. --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) bei Xunit.Sdk.ExecutionTimer.d__4.MoveNext() in C:\BuildAgent\work\cb37e9acf085d108\src\xunit.execution\Sdk\Frameworks\ExecutionTimer.cs:Zeile 48. --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde --- bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) bei Xunit.Sdk.ExceptionAggregator.d__9.MoveNext() in C:\BuildAgent\work\cb37e9acf085d108\src\xunit.core\Sdk\ExceptionAggregator.cs:Zeile 90.

System.FormatException

System.FormatException

无法从 BsonType 'Document' 反序列化一个 'List'.

Cannot deserialize a 'List' from BsonType 'Document'.

贝MongoDB.Bson.Serialization.Serializers.EnumerableSerializerBase2.Deserialize(BsonDeserializationContext上下文,BsonDeserializationArgs args) beiMongoDB.Bson.Serialization.Serializers.SerializerBase1.MongoDB.Bson.Serialization.IBsonSerializer.Deserialize(BsonDeserializationContext上下文,BsonDeserializationArgs args) beiMongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize(IBsonSerializer序列化器,BsonDeserializationContext 上下文) beiMongoDB.Bson.Serialization.BsonClassMapSerializer`1.DeserializeMemberValue(BsonDeserializationContext上下文,BsonMemberMap memberMap)

bei MongoDB.Bson.Serialization.Serializers.EnumerableSerializerBase2.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) bei MongoDB.Bson.Serialization.Serializers.SerializerBase1.MongoDB.Bson.Serialization.IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) bei MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize(IBsonSerializer serializer, BsonDeserializationContext context) bei MongoDB.Bson.Serialization.BsonClassMapSerializer`1.DeserializeMemberValue(BsonDeserializationContext context, BsonMemberMap memberMap)

如果存在相同的DateOfDay",则更新DayRecord的方法,否则将插入新的.

This is the method that Updates the DayRecord if one with the same "DateOfDay" exists, otherwise it will insert a new one.

    public async Task<bool> UpdateDayRecord(Guid storeID, DbDayRecord dayRecord)
    {
        var stores = GetUserStores();

        var builder = Builders<UserDayStore>.Filter;
        var filter = builder.Eq("Id", storeID);
        var result = await stores.FindAsync(filter);

        if (!await result.AnyAsync()) // Check is a Store with that Id exists
        {
            return false;
        }
        dayRecord.StoreId = storeID;

        filter =  builder.ElemMatch("Days", Builders<DbDayRecord>.Filter.Eq("DateOfDay", dayRecord.DateOfDay));
        result = await stores.FindAsync(filter);


        if (await result.AnyAsync())
        {

            var update = Builders<UserDayStore>.Update.Set("Days", dayRecord).CurrentDate("LastModified");

            var updateResult = await stores.UpdateOneAsync(filter, update);

            return (updateResult.ModifiedCount == 1);
        }
        else
        {

            filter = Builders<UserDayStore>.Filter.Eq("Id", storeID);
            var update = Builders<UserDayStore>.Update.AddToSet("Days", dayRecord).CurrentDate("LastModified");

            var updateResult = await stores.UpdateOneAsync(filter, update);

            return (updateResult.ModifiedCount == 1);
        }
    }

在调用该方法并更新现有 DayRecord 后,我在尝试访问 UserDayStore 时收到上述异常:

After the method is called and Updates an existing DayRecord I get the Exception above when trying access the UserDayStore:

    public async Task<Guid> GetStoreId (string username)
    { 
        var stores = GetUserStores();

        var filter = Builders<UserDayStore>.Filter.Eq("UserName", username);

        var result = await stores.FindAsync(filter);

        return result.First().Id;
    }

它在 FindAsync 调用中失败.

It fails in the FindAsync call.

这是更新后 JSON 文档的样子

This is what the JSON Document looks like after the update

{
    "_id" : LUUID("e858f1cc-c81d-7244-b8a0-8beec3c8e10d"),
    "LastModified" : ISODate("2016-04-23T10:43:17.293Z"),
    "UserName" : "TestUser",
    "Password" : "4242",
    "EndOfSubscription" : ISODate("2016-06-22T22:00:00.000Z"),
    "active" : true,
    "Days" : {
        "StoreId" : LUUID("e858f1cc-c81d-7244-b8a0-8beec3c8e10d"),
        "LastModified" : ISODate("2016-04-24T00:00:00.000Z"),
        "DateOfDay" : ISODate("2016-04-23T00:00:00.000Z"),
        "Quote" : "Testquote1"
    }
}

推荐答案

经过一些尝试和错误,我想我知道找到了正确的方法:

After some try and error I think I know found the right way:

    filter =  builder.ElemMatch("Days", Builders<DbDayRecord>.Filter.Eq("DateOfDay", dayRecord.DateOfDay));
    result = await stores.FindAsync(filter);

    if (await result.AnyAsync())  // Record already exists, update it
    {

        var update = Builders<UserDayStore>.Update.Set("Days.$", dayRecord).CurrentDate("LastModified");

        var updateResult = await stores.UpdateOneAsync(filter, update);

        return (updateResult.ModifiedCount == 1);
    }
    else // Add new Record to array
    {

        filter = Builders<UserDayStore>.Filter.Eq("Id", storeID);
        var update = Builders<UserDayStore>.Update.AddToSet("Days", dayRecord).CurrentDate("LastModified");

        var updateResult = await stores.UpdateOneAsync(filter, update);

        return (updateResult.ModifiedCount == 1);
    }

重点在于:

    var update = Builders<UserDayStore>.Update.Set("Days.$", dayRecord).CurrentDate("LastModified");

添加 .$ 使 mongo 更新数组元素.

Adding the .$ makes mongo updating the array element.

这篇关于mongoDB:C# 驱动程序 V2 如何更新嵌套集合中的项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆