I am getting MongoDb.Bson.SerializationException: 'Element name '_t' is not valid.
I read all posts online that appear to be similar issue at first, however, in those posts, element name is specified, here, i am only getting '_t' even by trying different class objects.
var database = AppConfig.client.GetDatabase("test");
var collection = database.GetCollection<BsonDocument>("testcollection");
var filter = Builders<Student>.Filter.Eq(g => g.Name, "oldName");
var update = Builders<Student>.Update.Set(g => g.Name, "NewName");
var updateResult = await collection.UpdateOneAsync(filter.ToBsonDocument(), update.ToBsonDocument());
Also, for all examples i have seen online for UpdateOneAsync function, filter and update below do NOT need to be BSON documents, however, my code won't compile unless I do .ToBSONDocument() as above.
var updateResult = await collection.UpdateOneAsync(filter, update);
My class is minimal:
public class Student
{
[BsonElement("Name")]
public string Name { get; set; }
[BsonElement("Age")]
public int Age { get; set; }
}
Can someone please help figure out what is wrong with above?
Update: How to use render for Update.Set
var registry = BsonSerializer.SerializerRegistry;
var serializer = registry.GetSerializer<Student>();
var filter = Builders<Student>.Filter.Eq(g=> g.Name, "NewName").Render(serializer, registry);
//I think update syntax is not correct.
var update = Builders<Student>.Update.Set(g => g.Name, "Changed").Render(serializer, registry);
//update is throwing error:cannot convert from Mongodb.bson.bsonvalue to mongodb.Driver.updatedefinition<MongoDB.Bson.BsonDocument
var updateResult = await collection.UpdateOneAsync(filter, update);
it's impossible to use ToBsonDocument as you did. The easiest fix is using not typed builders:
var filter = Builders<BsonDocument>.Filter.Eq("name", "oldName");
If you want to use typed builder, you should call Render as below:
var registry = BsonSerializer.SerializerRegistry;
var serializer = registry.GetSerializer<Student>();
var filter = Builders<Student>.Filter.Eq(e=>e.Name, "oldName").Render(serializer, registry);
Related
Is there a more efficient way of converting dynamo db data into concrete types? For example, when I query the data everything is in:
List<Dictionary<string, AttributeValue>>
Is it possible to easily convert the type without having to loop through each item and doing this all manually?
For example I am doing:
return items.Select(item => new Connection
{
ConnectionId = Guid.Parse(item["connectionId"].S),
ClientId = item["clientId"].S,
ProviderId = item["providerId"].S,
Scopes = item["scopes"].SS.ToArray(),
CredentialsId = item["credentialsId"].S,
Evidences = ToEvidences(item["consentEvidences"].L)
})
.ToList();
This then returns a list of my type Connection however I am explicitly mapping each field. Is there an easier way or a helper library that can do the mapping?
I think you'll have luck with the higher-level .NET Document model. It presents more natural data types.
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DotNetSDKMidLevel.html
The easiest way I have found is to use the Document.FromAttributeMap function to convert it to a Document object and then convert it again to the .NET type using the DynamoDBContext.FromDocument method as shown below.
public async Task<IEnumerable<WeatherForecast>> GetAll(string cityName)
{
var queryRequest = new QueryRequest()
{
TableName = nameof(WeatherForecast),
KeyConditionExpression = "CityName = :cityName",
ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
{
{":cityName", new AttributeValue(cityName)},
}
};
var response = await _dynamoDbClient.QueryAsync(queryRequest);
return response.Items.Select(a =>
{
var doc = Document.FromAttributeMap(a);
return _dynamoDbContext.FromDocument<WeatherForecast>(doc);
});
}
I am trying to recognize the entity "number" associated to the Intent command.
Here my entity in Luis
I use the Core Bot example and i let the classes names stay the same. https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/13.core-bot
I added the "number" entity here in flightbooking.cs
// Built-in entities
public DateTimeSpec[] datetime;
public double[] number;
I added this in flightbookingex.cs
public string Order_Number
=> Entities.number.ToString();
I created a class here : Order_Details.cs
namespace Microsoft.BotBuilderSamples
{
public class Order_Details
{
public string Order_Number { get; set; }
}
}
And when i want to retrieve the result in maindialog.cs
case FlightBooking.Intent.commande:
var commandemessagetext = "Voici le bon de commande";
var orderDetails = new Order_Details()
{
// Get destination and origin from the composite entities arrays.
Order_Number = luisResult.Order_Number,
};
var travelDateMsg = { result.Order_Number };
It says Cannot initialize an implicitly-typed variable with an array initializer and The name 'result' does not exist in the current context
I did not find another way to do this. I would like to display the result of travelDateMsg in the "case FlightBooking.Intent.commande". In the core bot example, it is displayed in another stepcontext.
i also tried the following piece of code, but it somehow does not work properly.
case FlightBooking.Intent.commande:
var commandemessagetext = "Here the order";
var order_count= luisResult.Entities;
var messageTexto = $"you have ordered {order_count}";
var message = MessageFactory.Text(messageTexto, messageTexto, InputHints.IgnoringInput);
await stepContext.Context.SendActivityAsync(message, cancellationToken);
the result is "you have ordered Microsoft.BotBuilderSamples.FlightBooking+_Entities"
Is there a simple way to return the value of an ententy in the same block of code than the one who detect the intent?
Thank you very much in advance for any suggestion on this
To answer the second error The name 'result' does not exist in the current context is because you have a typo:
case FlightBooking.Intent.commande:
var commandemessagetext = "Voici le bon de commande";
var orderDetails = new Order_Details()
{
// Get destination and origin from the composite entities arrays.
Order_Number = luisResult.Order_Number,
};
var travelDateMsg = { result.Order_Number };
There isn't a result there, there's a luisResult.
I am testing my asp.net core 2.2 web api with Postman. I write the JSON manually like this (httppatch):
{
"query": "{\"name\": \"foo\"}",
"update": [ "{\"$set\":{\"name\":\"foo2\"}}","{\"$set\":{\"path\": \"foo2 path\"}}" ]
}
Now I am thinking how can I build the patch body on the client side.
My question is how can I get the equivalent of this code in json to make it look like the one I write manually?
var query = Builders<T>.Filter.Eq(e => e.name, "foo");
var updates = Builders<T>.Update.Set(e => e.name, "foo2").Set(e => e.Path, "foo2 path");
I guess it's all about serialization, any idea how can I make it?
--Update--
I found this:
var serializerRegistry = BsonSerializer.SerializerRegistry;
var documentSerializer = serializerRegistry.GetSerializer<T>();
var upList = updates.Render(documentSerializer, serializerRegistry);
but it grabs only the last set it combines all sets in one (My bad, thanks to #Simon Mourier to pointing out my mistake !)
Here's the solution:
On the client side
// serializer
var serializerRegistry = BsonSerializer.SerializerRegistry;
var documentSerializer = serializerRegistry.GetSerializer<T>();
// filter and update
var filter = Builders<T>.Filter.Eq(e => e.Level, 2);
var updates = Builders<T>.Update
.Set(e => e.Name, "foo2")
.Set(e => e.Path, "foo2 path")
.Inc(e => e.Level, 1);
// get the string of the filter and the update
var filterString = filter.Render(documentSerializer, serializerRegistry);
var updateString = updates.Render(documentSerializer, serializerRegistry);
// instantiate patch object with properties to json
Patch patch = new Patch()
{
Query = filterString.ToJson(),
Update = updateString.ToJson()
};
// patch object to json
var patchJson = patch.ToJson();
On the server side
[HttpPatch]
public async Task<IActionResult> PatchOne([FromBody]Patch patch)
{
// don't need to ModelState.isValid, it's done on binding
try
{
var update = BsonDocument.Parse(patch.Update);
var filter = BsonDocument.Parse(patch.Query);
var result = await _serviceBase.UpdateOneAsync(filter, update);
...
}
catch (System.Exception ex)
{
return StatusCode(StatusCodes.Status500InternalServerError, ex.Message.ToJson());
}
}
Global Modals (my solution structure)
public class Patch
{
[Required]
public string Query { get; set; }
[Required]
public string Update { get; set; }
}
Thanks for your help !!
I Find a way to see the query
you need make the query and save it in var
var query = Builders<T>.Filter.Eq(e => e.name, "foo");
var makeQuery = _collection.Find(query).ToString();
makeQuery have the value of Filter.Eq
i am trying to find documents in collection by ids. Most of the suggested answers use C# class that matches with the document. something like here
var filter = Builders<Product>.Filter
.In(p => p.Id, productObjectIDs);
i don't have corresponding C# class, so i am using BsonDocument
public async Task<IEnumerable<BsonDocument>> GetData(IEnumerable<int> documentIds)
{
var collection = _mongoDatabase.GetCollection<BsonDocument>("mycollection");
// how do set filter here
var filterBuilder = Builders<BsonDocument>.Filter.In<int>("???????", documentIds);
var projection = Builders<BsonDocument>.Projection
.Include("_id")
.Include("status")
.Include("units");
var result = await collection.Find(filterBuilder).Project<BsonDocument>(projection).ToListAsync().ConfigureAwait(false);
return result;
}
I am not sure how do i set filter with in operator?
You may try this filter:
var filter = new BsonDocument("_id", new BsonDocument("$in", new BsonArray(documetIds)));
Based on this answer
I'm new to LINQ and Entity Framework and would appreciate some advice on the following scenario.
I have a entity model with two tables.
Travel_Request and Resource
Sample Fields
Travel_Request
Request_ID
Resource_ID
Resource
Resource_ID
Resource_Name
I would like to add the Resource_Name to the list when returning all the TRAVEL_REQUESTS
Thanks in advance
Hi you need to use the Linq join:
var data = from t in Travel_Request
join r in Resource on t.Resource_ID equals r.Resource_ID
select new
{
RequestId = t.Request_ID,
ResourceId = t.Resource_ID,
ResourceName = r.Resource_Name
};
If you already have an EF association then it could simply be:
var data = from t in Travel_Request
select new
{
RequestId = t.Request_ID,
ResourceId = t.Resource_ID,
ResourceName = t.Resource.Resource_Name
};
You will have to create a new object something like this.
var data = Travel_Request.Select(s=> new { Resource_Name = s.Recource.Resource_Name, Request_ID = s.Request_ID, Resource_ID = s.Resource_ID}).ToList();
As long as I've understood the question correctly this will work.
You can query Travel_Request entity and use the navigation propety to do that.
var resultList = DbContext.Travel_Request.Resources.where(x=>x.Resource_Name =="Your string").ToList();
I would add a model that has all three then do something like.
var TravelRequests =
from p in Travel_Request
from r in Resource.where(Res => Res.Resource_ID == p.Resource_ID)
select new TravelModel{
requestID = p.requestID,
Resource_ID = p.Resource_ID,
ResourceName = r.ResourceName
};
But thats just an example of how I would do it and there might be better ways. Also syntax might be a little off but general idea is there.
Use the Join:
Travel_Request.Join(Resource, tr => tr.ResourceId, r => r.ResourceId, (tr, r) => new { RequestId = tr.RequestId, ResourceId = tr.ResourceId, Name = r.ResourceName})
Or what a better practice would be is adding a Navigation property to TravelRequest.
TravelRequest would look like this:
int RequestId { get; set; }
int ResourceId{ get; set; }
[ForeignKey("ResourceId")]
Resource Resource { get; set; }
This way you can use Include
DBContext.TravelRequests.Include("Resource").First().Resource.Name;
Include tells EF to get the Resource with the TravelerRequest