Suppose that the table "Items" is empty and then the following code is executed:
var codes = new List<string>{ "aaa", "aaa" }
foreach (var code in codes)
{
var item = dbContext.Items.SingleOrDefault(r => r.Code.Equals(code)); // (*)
if (item == null)
{
item = new Item();
item.code = code;
dbContext.Items.Add(item);
}
}
dbContext.SaveChanges();
Question:
The resultant table "Items" will contain two "aaa" items or just one?
That is: in the second iteration the SingleOrDefault query (*) will search both in memory and db? or only in db?
Related
I'm iterating through the whole document, paragraph by paragraph. When a paragraph is in a table I want to store it in an array. But I don't want to store duplicates.
I tried to simply use indexOf, with == or with === but without success:
let tables = [];
// Iterate over the document
for (let i = 0; i < paragraphs.items.length; ++i)
{
// if this is in a table
if (paragraphs.items[i].tableNestingLevel > 0)
{
let table = paragraphs.items[i].parentTable;
table.load();
await context.sync();
// Try to avoid duplicates in the array (doesn't work)
if(tables.indexOf(table) == -1)
{
tables.push(table);
}
}
...
}
I know that document.body.tables exists, but I iterate over paragraphs to parse other structures than tables in the order they are in the document.
I am new in Entity Framework and I have a little question.
Is it possible to compare in "Where" with a number.
I will add code example.
var source = db.Book.Where(book => book.Count > 0);
So, I need to get all book items where count more than zero.
Thanks in advance for your help!
Here is the structure of database
I'm not sure why you are trying to query the entire table to check if there is any record, yet you can do something like:
var query = context.Books.Any() ? context.Books.ToList() : null;
if (query is not null)
{
query.ForEach(b =>
{
Console.WriteLine($"ID:{b.Id}, Title:{b.Title}");
});
}
However, if you are trying to find out if there is duplication available, you can use the following query:
var query = context.Books.FirstOrDefault(b => b.Title == "some title")
is not null ? context.Books.ToList() : null;
if (query is not null)
{
query.ForEach(b =>
{
Console.WriteLine($"ID:{b.Id}, Title:{b.Title}");
});
}
By the way, I don't think it is a good idea to have such a scenario.
I'm attempting to write data from a data table to a sheet via the smartsheet API (using c# SDK). I have looked at the documentation and I see that it supports bulk operations but I'm struggling with finding an example for that functionality.
I've attempted to do a work around and just loop through each record from my source and post that data.
//Get column properties (column Id ) for existing smartsheet and add them to List for AddRows parameter
//Compare to existing Column names in Data table for capture of related column id
var columnArray = getSheet.Columns;
foreach (var column in columnArray)
{
foreach (DataColumn columnPdiExtract in pdiExtractDataTable.Columns)
{
//Console.WriteLine(columnPdiExtract.ColumnName);
if(column.Title == columnPdiExtract.ColumnName)
{
long columnIdValue = column.Id ?? 0;
//addColumnArrayIdList.Add(columnIdValue);
addColumnArrayIdList.Add(new KeyValuePair<string, long>(column.Title,columnIdValue));
}
}
}
foreach(var columnTitleIdPair in addColumnArrayIdList)
{
Console.WriteLine(columnTitleIdPair.Key);
var results = from row in pdiExtractDataTable.AsEnumerable() select row.Field<Double?>(columnTitleIdPair.Key);
foreach (var record in results)
{
Cell[] cells = new Cell[]
{
new Cell
{
ColumnId = columnTitleIdPair.Value,
Value = record
}
};
cellRecords = cells.ToList();
cellRecordsInsert.Add(cellRecords);
}
Row rows = new Row
{
ToTop = true,
Cells = cellRecords
};
IList<Row> newRows = smartsheet.SheetResources.RowResources.AddRows(sheetId, new Row[] { rows });
}
I expected to generate a value for each cell, append that to the list and then post it through the Row Object. However, my loop is appending the column values as such: A1: 1, B2: 2, C3: 3 instead of A1: 1, B1: 2, C3: 3
The preference would be to use bulk operations, but without an example I'm a bit at a loss. However, the loop isn't working out either so if anyone has any suggestions I would be very grateful!
Thank you,
Channing
Have you seen the Smartsheet C# sample read / write sheet? That may be a useful reference. It contains an example use of bulk operations that updates multiple rows with a single call.
Taylor,
Thank you for your help. You lead me in the right direction and I figured my way through a solution.
I grouped by my column value list and built records for the final bulk operation. I used a For loop but the elements in each grouping of columns is cleaned and assigned a 0 prior to this method so that they retain the same count of values per grouping.
// Pair column and cell values for row building - match
// Data source column title names with Smartsheet column title names
List<Cell> pairedColumnCells = new List<Cell>();
//Accumulate cells
List<Cell> cellsToImport = new List<Cell>();
//Accumulate rows for additions here
List<Row> rowsToInsert = new List<Row>();
var groupByCells = PairDataSourceAndSmartsheetColumnToGenerateCells(
sheet,
dataSourceDataTable).GroupBy(
c => c.ColumnId,
c => c.Value,
(key, g) => new {
ColumnId = key, Value = g.ToList<object>()
});
var countGroupOfCells = groupByCells.FirstOrDefault().Value.Count();
for (int i = 0; i <= countGroupOfCells - 1; i++)
{
foreach (var groupOfCells in groupByCells)
{
var cellListEelement = groupOfCells.Value.ElementAt(i);
var cellToAdd = new Cell
{
ColumnId = groupOfCells.ColumnId,
Value = cellListEelement
};
cellsToImport.Add(cellToAdd);
}
Row rows = new Row
{
ToTop = true,
Cells = cellsToImport
};
rowsToInsert.Add(rows);
cellsToImport = new List<Cell>();
}
return rowsToInsert;
I know there's a way to do db.collection.getIndexes() Which will list all the indexes defined for a collection. Is there a way to copy and create those index definitions to another collection?
There's a lot of them and I don't want to do them one by one.
regarding the duplicated question comment: I do not wish to copy a collection. I wish to export indexes in a format that I can apply to another collection.
For example I have one existing user collection with indexes _id_, name_1, email_1 and website_1
Then I have another collection called usertest, I want to copy indexes from user collection to usertest collection. The following commands works for this scenario:
Copy both index key and index options
var indexes = db.user.getIndexes();
indexes.forEach(function(index){
delete index.v;
delete index.ns;
var key = index.key;
delete index.key
var options = [];
for (var option in index) {
options.push(index[option]);
}
db.usertest.createIndex(key, options);
});
Copy index key only (batch processing)
var indexKeys = db.user.getIndexKeys();
db.usertest.createIndexes(indexKeys);
Hope this will be helpful. Here's the doc: createIndexes
To do this directly in MongoDB do the following,
The following command will generate mongo DB queries for existing indexes of all collections,
db.getCollectionNames().forEach(function(col) {
var indexes = db[col].getIndexes();
indexes.forEach(function (c) {
var fields = '', result = '', options = {};
for (var i in c) {
if (i == 'key') {
fields = c[i];
} else if (i == 'name' && c[i] == '_id_') {
return;
} else if (i != 'name' && i != 'v' && i != 'ns') {
options[i] = c[i];
}
}
var fields = JSON.stringify(fields);
var options = JSON.stringify(options);
if (options == '{}') {
result = "db." + col + ".createIndex(" + fields + "); ";
} else {
result = "db." + col + ".createIndex(" + fields + ", " + options + "); ";
}
result = result
.replace(/{"floatApprox":-1,"top":-1,"bottom":-1}/ig, '-1')
.replace(/{"floatApprox":(-?\d+)}/ig, '$1')
.replace(/\{"\$numberLong":"(-?\d+)"\}/ig, '$1');
print(result);
});
});
The above command will output something like the following, based on the amount of collection you have
db.User.createIndex({"createdAt":-1}, {"background":true});
db.User.createIndex({"updatedAt":-1}, {"background":true});
db.Login.createIndex({"loginDate":-1}, {"background":true});
So after executing this, copy the MongoDB queries that are generated above to create the indexes to the new collection, Change the collection name in that then execute it.
For eg: to copy all indexes belonging to the User collection to the UserNew collection, I will rename the query's old collection name to new like the following and execute it, that is it, now you have all the indexes copied to a new collection from the old one.
db.UserNew.createIndex({"createdAt":-1}, {"background":true});
db.UserNew.createIndex({"updatedAt":-1}, {"background":true});
Credits: http://aleksandrmaiorov.com/2019/04/29/mongo-how-to-copy-indexes-from-one-database-to-another/
Thank you for the answer from Rocky and Bloke which helped me a lot
here is the consolidated version as suggested by Bloke.
and in PRODUCTION. we would like to make sure the background: true
is used to avoid slave halt query when indexes creation replicated.
var indexes = db.user.getIndexes();
// we skipped the __id__ indexes and set the default background: true option
indexes.forEach(function(index){
if(index.name =='_id_'){
print("we are skip the _id_ index")
}else{
delete index.v;
delete index.ns;
var key = index.key;
delete index.key
var options = {};
for (var option in index) {
options[option] = index[option]
}
options['background'] = true;
printjson(key);
printjson(options);
db.usertest.createIndex(key, options);
}
});
Rocky Li's answer was helpful but did not create the index options properly at the time of writing (It gathered the option values but not the keys). The following modification worked for me:
var indexes = db.user.getIndexes();
indexes.forEach(function(index){
delete index.v;
delete index.ns;
var key = index.key;
delete index.key
// uncomment if you want to ensure creation is in background
//if(!('background' in index))
//index['background'] = true;
db.user.createIndex(key, index);
});
Copy all indexes from one database another database
use firstDbName;
var indexKeyArray = [];
db.getCollectionNames().forEach(function(collection) {
var indexKeys = db[collection].getIndexKeys();
var base = {};
base["name"] = collection;
base["indices"] = indexKeys
indexKeyArray.push(base);
});
#printjson(indexKeyArray);
use destinationDbName;
indexKeyArray.forEach(function(data) {
db[data.name].createIndexes(data.indices);
});
here is a snippet of my code:
using (var uow = new UnitOfWork())
{
//ItemType itself
ItemType itemType1 = uow.ItemTypeRepository.Get(i => i.Name == "ServerTypeList").FirstOrDefault();
Assert.IsTrue(itemType1.ID != null);
var itemType2 = uow.ItemTypeRepository.Get(i => i.Name == "ServerTypeList", orderBy: o => o.OrderBy(d => d.Name), includeProperties: "Items");
//itemType2[0].
...
I am trying to list all the items inside itemType2 ("Get" method returns an IEnumerable):
What's wrong with itemType2.First().Items[0]?
This works because itemType2 is a sequence. Based on what you're seeing in the debugger, it has only one element. If it always has only one element, then you should use itemType2.Single().Items[0] instead.
Every element of this sequence has an Items property, which appears to be a list or array or something else that can be indexed, so once you get there, you can index into it, as above, or you can iterate over it:
foreach (var item in itemType2.Single().Items)
{
// Do something with each item in the sequence
}