Mongodb C# driver Insert new child of object to parents - mongodb

I want to insert new child on the record below and i use this code on .net core
var builder = Builders<parent>.Filter;
var filter = builder.Eq("_id", "123");
var update = Builders<parent>.Update.AddToSet<IEnumerable<Child>>
("Child", Child);
await _expensesContext.collection.UpdateOneAsync(filter, update);
parent
{
"_Id": "123"
"Child": [
{"Id": "1234", "name": "jhon"}
]
}
but i enconter this error Unable to cast object of type 'System.Collections.Generic.List`1[child]' to type 'Child'.'

I fixed this using addtosetEach instead of addtoset:
var builder = Builders<parent>.Filter;
var filter = builder.Eq("_id", "123");
var update = Builders<parent>.Update.AddToSetEach<IEnumerable<Child>>
("Child", Child);
await _Context.collection.UpdateOneAsync(filter, update);

Related

How to update a record and update include many records relationship by foreignKey in sequelize use db postgres

I create an API that updates a record associated with a foreign key
if I just put a value to items so I want it to return remove other values that I don't put
if I edit some value in items so I want it to return the value that I edited
if I put value over value of items so I want it to return the old value of items and the value that I put over
example: const record = {id:1,name:"abc",items:[{id:1,name:"abc",recordId:1},{id:2,name:"abcd",recordId:1}]}
const update = await dbRecord.update({id,name},{where: {id: req.params.id},include:[model:'items',id:[1,2]});
You can use Sequelize mixins. Sequelize has special methods that uses the prefix get add set concatenated with the model name.
const update = await dbRecord.update(
{ id, name },
{ where: { id: req.params.id } }
);
//array get from body
ex: array = [
{ id: 1, name: "abc", recordId: 1 },
{ id: 2, name: "abcd", recordId: 1 },
];
const itemId = array.map((arr) => arr.id);
// result = [1,2]
await dbItems.bulkCreate(array, {
updateOnDuplicate: ["name"],
});
for (var i = 0; i < update.items.length; i++) {
const item = update.items[i];
if (!itemId.includes(container.id)) {
await container.destroy();
}
}
so it create update delete in once time.

How to initiate a var which will store array of values with different datatypes?

I have a dynamic expression built in .net, which works if the column type is string, however, if the column is date or int then i have to convert the input to the respective datatype before passing to the expression. How can I make it dynamic?
MemberExpression member = Expression.Property(param, filter.Name);
var propertyType = ((PropertyInfo)member.Member).PropertyType;
if (propertyType.GetType() == typeof(Int32))
{
var criteria = Array.ConvertAll(filter.Value, Int32.Parse);
}
else if (propertyType.GetType() == typeof(DateTime))
{
var criteria = Array.ConvertAll(filter.Value, DateTime.Parse);
}
else
{
var criteria = filter.Value;
}
criteria.Aggregate( // -- gives error here since criteria does not exist in current context
(Expression)Expression.Constant(false),
(acc, next) =>
Expression.MakeBinary(
ExpressionType.Or,
acc, Expression.Equal(member, Expression.Constant(next))));
I already tried defining
var criteria = null;
var criteria = object[];
dynamic criteria;
var criteria = new {};
Payload
{
"pageFilters": [
{
"name": "string",
"condition": "Equals",
"value": [
"string"
]
}
]
}

Search field: Filtering nested object

Hi all,
I have the following data structure :
[ {
"supplierCode": "supplier1",
"supplierDesc": "supplier1Desc",
"pos": [ {
"poNum": "11111",
"materialNum": "matNum11",
"materialDesc": "matDesc11"
},
{ "poNum": "11112",
"materialNum": "matNum22",
"materialDesc": "matDesc22"}
] },
{"supplierCode": "supplier2",
"supplierDesc": "supplier2Desc",
"pos": [ {
"poNum": "22222",
"materialNum": "matNum11",
"materialDesc": "matDesc11"},
{"poNum": "22223",
"materialNum": "matNum22",
"materialDesc": "matDesc22"}]
}
]
My task is to filter data in JSON model by properties in pos array.
I tried the following approach:
myList = this.getView().byId("myList");
var binding = myList.getBinding("items");
if (!query) {
binding.filter([]);
} else {
binding.filter([new sap.ui.model.Filter([
new sap.ui.model.Filter("supplierCode", sap.ui.model.FilterOperator.Contains, query),
new sap.ui.model.Filter("supplierDesc", sap.ui.model.FilterOperator.Contains, query),
new sap.ui.model.Filter("pos/materialDesc", sap.ui.model.FilterOperator.Contains, query)
], false)]);
}
with no luck.
Also, I found out it is possible to do with ODataModel, but I didn't find anything regarding JSONModel.
Can such filtering be done at all?
Thank you.
Here is an example on test function under the constructor of the Filter :
Filter result will return a line of list containing the materialDesc description introduced in the filter :
onFilterInvoices: function(oEvent) {
// build filter array
var aFilter = [];
var sQuery = oEvent.getParameter("query");
if (sQuery) {
aFilter.push(new sap.ui.model.Filter({
path: "pos",
test: function(oValue) {
var oMaterials = oValue;
for (var i in oMaterials) {
if (oMaterials[i].materialDesc === sQuery) {
return true;
}
}
return false;
}
}));
}
// filter binding
var oList = this.getView().byId("listapp");
var oBinding = oList.getBinding("items");
oBinding.filter(aFilter);
}

MongoDB C# Driver Update Collection with Concatenated string

How do I convert this SQL to MongoDB query using C# Driver
UPDATE dbo.MyTable SET ConcatField = CONCAT(Field1, Field2, Field3, Field4, Field5)
WHERE Id = 21
Using MongoDB.Driver 2.2.3.3
I need MongoDB query using BsonDocument type, I don't have Strong types for my Mongo Collections as Collection is not based on fixed schema.
Trying something like this
var items = myCollection.FindSync(filter).ToList();
foreach (var item in items)
{
UpdateDefinition<BsonDocument> updateDefinition =
new BsonDocumentUpdateDefinition<BsonDocument>(item.Merge(ListOfStrinForSelectedFields.ToBsonDocument()));
myCollection.UpdateManyAsync(filter, updateDefinition);
}
This will be my Shell Script
var cursor = db.MyCollection.find({ "Id": 21 }), // Or what ever your find conditions is
bulkUpdateOps = [];
cursor.forEach(function(doc){
var ConcatField = doc.Field1 + doc.Field2 + doc.Field3 ;
bulkUpdateOps.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": { "$set": { "MyConCatField": ConcatField } }
}
});
if (bulkUpdateOps.length == 1000) {
db.MyCollection.bulkWrite(bulkUpdateOps);
bulkUpdateOps = [];
}
});
if (bulkUpdateOps.length > 0) { db.MyCollection.bulkWrite(bulkUpdateOps); }
then execute it in c# with RunCommandAsync method from MongoDatabase.
var result = await mongoDatabase.RunCommandAsync<BsonDocument>(BsonDocument.Parse(command));
Note: you will have to modify the command string using pipelines and parse it to BsonDocument.

UnitTesting EF6 with OfType<T>

I am trying to follow the guidelines provided http://msdn.microsoft.com/en-us/library/dn314429.aspx by Microsoft for Unittesting DbSets. All was going well - as they documented. Until I got to some code which works with a inheritance table. Since OfType() is an extension method, I cannot figure out how to create a Mock which will work to keep my code testable.
To clarify: I am trying to Test My Service Layer, which take a DBContext which is Injected, and which exposes several DbSets. In particular, I have an abstract History class, which has concrete derived types of StaffHistory, ContactHistory, etc. As a result, I only have 1 DbSet on my Dbcontext, which is of type History. I then use the Extension method OfType to set the discriminator and query the particular type.
When I create a Mock DbSet all usually works fine, except the OfType extension method fails, reporting NullReference Exception.
Any ideas or tips?
Service Layer:
public IEnumerable<ContactHistory> GetContactHistory(int ContactId, int AgeInDays)
{
var age = DateTimeOffset.Now.AddDays(-Math.Abs(AgeInDays));
return context.History.OfType<ContactHistory>()
.Where(h => h.ContactId == ContactId && h.CreatedAt >= age)
.AsEnumerable();
}
Unit Test Code:
[TestMethod]
public void History_Returns_Limited_Results()
{
var testData = new List<ContactHistory> {
new ContactHistory {
ContactId = 1,
CreatedAt = DateTimeOffset.Now,
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = DateTimeOffset.Now.AddDays(-61),
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = DateTimeOffset.Now.AddDays(-60),
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = DateTimeOffset.Now,
UserName = "UserA",
Action = "Action",
}
}.AsQueryable();
// Setup
var mockContext = new Mock<IPEContext>();
var mockSet = new Mock<IDbSet<History>>();
mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.Provider).Returns(testData.Provider);
mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.Expression).Returns(testData.Expression);
mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.ElementType).Returns(testData.ElementType);
mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.GetEnumerator()).Returns(testData.GetEnumerator());
mockContext.Setup(c => c.History).Returns(mockSet.Object);
// Test
var service = new HistoryService(mockContext.Object);
var historyFound = service.GetContactHistory(4, 60);
// Verify
Assert.IsNotNull(historyFound);
Assert.AreEqual(2, historyFound.Count());
}
Is there something flawed in my approach? Is there something flawed in how I have setup my mock? This was following the Microsoft Article I mentioned above so that I could test service logic acting on a DbSet. The only flaw seems to be the Extension Method - not sure how I should work around that.
OK - I have figured this out. Of course there was a simple answer, but one which eluded me, because I had already mapped the Linq Provider and all in as the Type IQueryable. If you are using the .OfType() method, your mock must return on the Untyped Queryable method.
Here is the test code to allow the Method to work properly:
[TestMethod]
public void History_Returns_Limited_Results()
{
var today = new DateTimeOffset(DateTime.Today, DateTimeOffset.Now.Offset);
var testData = new List<ContactHistory> {
new ContactHistory {
ContactId = 1,
CreatedAt = today,
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = today.AddDays(-61),
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = today.AddDays(-60),
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = today,
UserName = "UserA",
Action = "Action",
}
}.AsQueryable();
// Setup
var mockContext = new Mock<IPEContext>();
var mockSet = new Mock<IDbSet<History>>();
mockSet.As<IQueryable>().Setup(m => m.Provider).Returns(testData.Provider);
mockSet.As<IQueryable>().Setup(m => m.Expression).Returns(testData.Expression);
mockSet.As<IQueryable>().Setup(m => m.ElementType).Returns(testData.ElementType);
mockSet.As<IQueryable>().Setup(m => m.GetEnumerator()).Returns(testData.GetEnumerator());
mockContext.Setup(c => c.History).Returns(mockSet.Object);
// Test
var service = new HistoryService(mockContext.Object);
var contact = new Person { ContactId = 4 };
var historyFound = service.GetContactHistory(contact, 60);
// Verify
Assert.IsNotNull(historyFound);
Assert.AreEqual(2, historyFound.Count());
}