简体   繁体   中英

MongoDB Unable to determine the serialization information for the expression error

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.

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));

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; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM