.net c#更新数组,索引出现问题

Updating array, trouble with index
2020-10-17
  •  译文(汉语)
  •  原文(英语)

使用mongodb c#驱动程序时,我的代码遇到了麻烦.此问题看起来像这里描述的问题:http : //www.ciiycode.com/0iiBNWWexjex/how-to-update-items-in-an-arraylist-with-mongo-c-driver.html 似乎已经解决了.

我想更新文档中的二维数组.如果我用

myarray[0,3] 

它有效,但是如果我使用像

int a = 0;
int b = 3;
myarray[a,b]

它给我一个"无法确定表达式的序列化信息..."错误

完整代码:

int a = 0;
int b = 3;    
var update = Builders<sensorValuesDocument>.Update                  
                    .Set(e => e.values[a][b]
                    , new sensorValues()
                    {
                        v = 0,
                        t = 0,
                        h = 0,
                        c = 0,
                        l = 0
                    }) ...

和我的文档类:

public class sensorValuesDocument
    {
        ...
        public List<List<sensorValues>> values { get; set; }
        ...
    }

 public class sensorValues
    {
        [BsonRepresentation(BsonType.Double, AllowTruncation = true)]
        public float? t { get; set; }
        [BsonRepresentation(BsonType.Double, AllowTruncation = true)]
        public float? v { get; set; }
        [BsonRepresentation(BsonType.Double, AllowTruncation = true)]
        public float? h { get; set; }
        [BsonRepresentation(BsonType.Double, AllowTruncation = true)]
        public float? l { get; set; }
        [BsonRepresentation(BsonType.Double, AllowTruncation = true)]
        public float? c { get; set; }
    }

如果我用.Set(e => e.values [0] [3]替换以前的代码,它就可以了.有什么想法/解决方法吗?

朱利安

速聊1:
这应该是表达式树的Mongo驱动程序问题,它无法从变量中提取数组索引,并且需要文字.
速聊2:
也许我应该在他们的网站上提交错误?
速聊3:
也许吧 BTW文档说,此更新方法已过时.我错了吗?
速聊4:
嗯,不,我不这么认为,这是官方文档中展示的方法.无论如何,我们将看到我将提交错误解决方案请求
解决过程1

我想这是MongoDB C#驱动程序的问题,.Set(...)当数组访问的索引是变量时,它无法转换整个表达式树.

幸运的是,C#是一种非常强大的语言,它支持表达式树,使您可以以编程方式创建像数据结构一样的表达式.

最终,您需要这样的表达式:listOfLists => listOfLists [0][3]使用整数文字,对吗?

请参见以下代码:

int a = 0;
int b = 3;

// This is the input parameter for the expression (i.e. the (doc) => part of the expression)
ParameterExpression valuesDocumentParameter = Expression.Parameter(typeof(sensorValuesDocument));
// This is the "values" property access. Now we would have the following expression:
// (doc) => doc.values
MemberExpression listOfListPropertyAccess = Expression.Property(valuesDocumentParameter, "values");

// This is accessing the parent list: (doc) => doc.values[0]
IndexExpression parentListIndexerAccess = Expression.Property
(
    listOfListPropertyAccess, 
    "Item", 
    new Expression[] { Expression.Constant(a) }
);

// This is accessing the nested list: (doc) => doc.values[0][3]
IndexExpression nestedListIndexerAccess = Expression.Property
(
    parentListIndexerAccess, 
    "Item", 
    new Expression[] { Expression.Constant(b) }
);

// This builds the full expression tree!
Expression<Func<sensorValuesDocument, sensorValues>> setExpr =
    Expression.Lambda<Func<sensorValuesDocument, sensorValues>>
    (
        nestedListIndexerAccess,
        valuesDocumentParameter
    );

现在,你可以给setExprUpdate.Set(...):Update.Set(setExpr).

我相信这应该可以解决MongoDB驱动程序的问题,因为您所提供的是它真正的期望:使用文字而不是变量的数组访问.

速聊1:
谢谢Matias.这是一种强大且复杂的方法.我尝试了您的解决方案,但类型不匹配.也许是因为sensorValues不是直接查询的对象,而是我应该查询e.values(如果您查看sensorValueDocument定义,则为嵌套列表)?参数1:无法从'System.Linq.Expressions.Expression <System.Func <Models.sensorValues [ , ],Models.sensorValues >>'转换为'System.Linq.Expressions.Expression <System.Func <Controllers.sensorValuesDocument,型号.传感器值>>'
速聊2:
嗯,是的...我知道了.它需要进行一些修改才能构建正确的表达式树.如果您可以等到明天再解决.如果可以的话,我会尽力解决.
速聊3:
感谢Matias的帮助.我很高兴能得到您的优雅解决方案:-)同时,我通过构造以值数组项为目标的字符串找到了一种(实际上不太漂亮的)解决方法:.Set("values." + a +"." + b,新的sensorValues()...
速聊4:
终于我做到了!:)尝试更新的代码.我已从上一个答案的版本中删除了重用部分,因为我相信这里的概括根本无关紧要...让我知道它是否有效!
速聊5:
我尝试了您的代码,但是出现了相同类型的错误:ExceptionMessage =无法确定Param_0 => Param_0.values.Item [17] .Item [2]的序列化信息.显然,该问题已被推迟到另一个变量:-/无论如何,感谢您的帮助,我暂时坚持使用"丑陋"的解决方案;-)

I have a trouble with my code, using mongodb c# driver. This trouble looks like the one described here : http://www.ciiycode.com/0iiBNWWexjex/how-to-update-items-in-an-arraylist-with-mongo-c-driver.html which seems to have been solved.

I want to update a bi-dimensionnal array in my document. If I use

myarray[0,3] 

it works, however if I use variable like

int a = 0;
int b = 3;
myarray[a,b]

it gives me a "Unable to determine the serialization information for the expression ..." error

Full code :

int a = 0;
int b = 3;    
var update = Builders<sensorValuesDocument>.Update                  
                    .Set(e => e.values[a][b]
                    , new sensorValues()
                    {
                        v = 0,
                        t = 0,
                        h = 0,
                        c = 0,
                        l = 0
                    }) ...

and my document class :

public class sensorValuesDocument
    {
        ...
        public List<List<sensorValues>> values { get; set; }
        ...
    }

 public class sensorValues
    {
        [BsonRepresentation(BsonType.Double, AllowTruncation = true)]
        public float? t { get; set; }
        [BsonRepresentation(BsonType.Double, AllowTruncation = true)]
        public float? v { get; set; }
        [BsonRepresentation(BsonType.Double, AllowTruncation = true)]
        public float? h { get; set; }
        [BsonRepresentation(BsonType.Double, AllowTruncation = true)]
        public float? l { get; set; }
        [BsonRepresentation(BsonType.Double, AllowTruncation = true)]
        public float? c { get; set; }
    }

If I replace the previous code with .Set(e => e.values[0][3] It works just fine. Any idea/workaround please ? Thanks in advance

Julien

Talk1:
It should be a Mongo driver issue with expression trees, where it can't extract array indexes from variables and it requires literals..
Talk2:
Maybe should I file a bug on their website ?
Talk3:
Maybe, maybe. BTW docs says that this update method is obsolete. Am I wrong?
Talk4:
mmmmh no, I don't think so, and this is the method showcased in the official documentation. Anyway we'll see I am going to submit a bug resolution request
Solutions1

I guess it's some issue with MongoDB C# driver where it can't translate the whole .Set(...) expression tree when array access' indexes are variables.

Fortunately, C# is a very very powerful language and it supports expression trees which let you programatically-create expressions like a data structure.

At the end of the day, you need an expression like this: listOfLists => listOfLists [0][3] using integer literals, right?

See the following code:

int a = 0;
int b = 3;

// This is the input parameter for the expression (i.e. the (doc) => part of the expression)
ParameterExpression valuesDocumentParameter = Expression.Parameter(typeof(sensorValuesDocument));
// This is the "values" property access. Now we would have the following expression:
// (doc) => doc.values
MemberExpression listOfListPropertyAccess = Expression.Property(valuesDocumentParameter, "values");

// This is accessing the parent list: (doc) => doc.values[0]
IndexExpression parentListIndexerAccess = Expression.Property
(
    listOfListPropertyAccess, 
    "Item", 
    new Expression[] { Expression.Constant(a) }
);

// This is accessing the nested list: (doc) => doc.values[0][3]
IndexExpression nestedListIndexerAccess = Expression.Property
(
    parentListIndexerAccess, 
    "Item", 
    new Expression[] { Expression.Constant(b) }
);

// This builds the full expression tree!
Expression<Func<sensorValuesDocument, sensorValues>> setExpr =
    Expression.Lambda<Func<sensorValuesDocument, sensorValues>>
    (
        nestedListIndexerAccess,
        valuesDocumentParameter
    );

Now you can give setExpr to Update.Set(...): Update.Set(setExpr).

I believe that this should do the trick and workaround the MongoDB driver's issue, since you're giving what it really expects: an array access using literals instead of variables.

Talk1:
Thanks Matias. This is kind of powerful, and complicated as well. I tried your solution and I get a type mismatch. Maybe is it because the sensorValues is not directly the object I am querying, but instead I should query e.values (which is the nested list if you look at the sensorValueDocument definition) ? Argument 1: cannot convert from 'System.Linq.Expressions.Expression<System.Func<Models.sensorValues[,], Models.sensorValues>>' to 'System.Linq.Expressions.Expression<System.Func<Controllers.sensorValuesDocument, Models.sensorValues>>'
Talk2:
Ah, yeah... I see... it requires few modifications to build up the right expression tree... If you can wait until tomorrow I'll fix it. I'll try to get it fixed before if I can
Talk3:
Thanks Matias for your help. I would be glad to have your elegant solution :-) In the meantime, I found a (really less beautiful) workaround by constructing the string to target the values array item : .Set("values." + a + "." + b, new sensorValues() ...
Talk4:
Finally I did it! :) Try my updated code. I've removed the re-use part from the previous answer's versión because I believe that a generalization here wouldn't matter at all... Let me know if it worked!
Talk5:
I tried your code, however I get the same type of error : ExceptionMessage=Unable to determine the serialization information for Param_0 => Param_0.values.Item[17].Item[2] . Apparently, the problem has just be postponed to another variable :-/ Anyway thanks for your help, I stick with my "ugly" solution for now ;-)
转载于:https://stackoverflow.com/questions/30816625/updating-array-trouble-with-index

本人是.net程序员,因为英语不行,使用工具翻译,希望对有需要的人有所帮助
如果本文质量不好,还请谅解,毕竟这些操作还是比较费时的,英语较好的可以看原文

留言回复
我们只提供高质量资源,素材,源码,坚持 下了就能用 原则,让客户花了钱觉得值
上班时间 : 周一至周五9:00-17:30 期待您的加入