可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
My data is having following structure
public enum ParamType { Integer=1, String=2, Boolean=3, Double=4 } public class Gateway { public int _id { get; set; } public string SerialNumber { get; set; } public List<Device> Devices { get; set; } } public class Device { public string DeviceName { get; set; } public List<Parameter> Parameters { get; set; } } public class Parameter { public string ParamName { get; set; } public ParamType ParamType { get; set; } public string Value { get; set; } }
I filled 10 document objects of Gateway in a MongoDB database. Now I want to query all those gateways which contains a device having Parameter with ParamName
as "Target Temperature" and whose Value
> 15.
I created following queries
var parameterQuery = Query.And(Query<Parameter>.EQ(p => p.ParamName, "Target Temperature"), Query<Parameter>.GT(p => int.Parse(p.Value), 15)); var deviceQuery = Query<Device>.ElemMatch(d => d.Parameters, builder => parameterQuery); var finalQuery = Query<Gateway>.ElemMatch(g => g.Devices, builder => deviceQuery);
But when I run this, it is giving an exception
Unable to determine the serialization information for the expression: (Parameter p) => Int32.Parse(p.Value)
Please suggest where I am wrong.
回答1:
As the error suggests, you can't use Int32.Parse
inside your query. This lambda expression is used to get out the name of the property and it doesn't understand what Int32.Parse
is.
If you are querying a string, you need to use a string value for comparison:
var parameterQuery = Query.And(Query<Parameter>.EQ(p => p.ParamName, "Target Temperature"), Query<Parameter>.GT(p => p.Value, "15"));
However, that's probably not what you want to do since you're using GT
. To be treated as a number for this comparison you need the value to actually be an int in mongo, so you would need to change the type of your property:
public class Parameter { public string ParamName { get; set; } public ParamType ParamType { get; set; } public int Value { get; set; } } var parameterQuery = Query.And(Query<Parameter>.EQ(p => p.ParamName, "Target Temperature"), Query<Parameter>.GT(p => p.Value, 15));
回答2:
Summary
I ran into this when I was modifying a list. It appears that Linq First/FirstOrDefault
was not handled well by MongoDB for me. I changed to be an array index var update = Builders<Movie>.Update.Set(movie => movie.Movies[0].MovieName, "Star Wars: A New Hope");
Note: This is in Asp.Net 5 using MongoDB.Driver 2.2.0.
Full Example
public static void TypedUpdateExample() { var client = new MongoClient("mongodb://localhost:27017"); var database = client.GetDatabase("test"); var collection = database.GetCollection<Movie>("samples"); //Create some sample data var movies = new Movie { Name = "TJ", Movies = new List<MovieData> { new MovieData { MovieName = "Star Wars: The force awakens" } } }; collection.InsertOne(movies); //create a filter to retreive the sample data var filter = Builders<Movie>.Filter.Eq("_id", movies.Id); //var update = Builders<Movie>.Update.Set("name", "A Different Name"); //TODO:LP:TSTUDE:Check for empty movies var update = Builders<Movie>.Update.Set(movie => movie.Movies[0].MovieName, "Star Wars: A New Hope"); collection.UpdateOne(filter, update); } public class Movie { [BsonId] public ObjectId Id { get; set; } public string Name { get; set; } public List<MovieData> Movies { get; set; } } public class MovieData { [BsonId] public ObjectId Id { get; set; } public string MovieName { get; set; } }