I need to show the result of a multiple selection and do not know how I can handle, the problem is as follows:
I have a tree, which is multipleselection, selecting the first time, this shows me the correct information, but when I select another node, the information should be displayed for the first and the second selection, but only show the second.
My question is, how I can store the previous selection and link this with the new one ..? I'm working with NHibernate, C # and the MVC model.
I appreciate any help.
Sincerely
you can Query for multiple Selections
IEnumerable<Entity> results = Enumerable.Empty<Entity>();
foreach (var node in selectedNodes)
{
results = results.Concat(Session.Query<Entity>().Where(...).Future<Entity>());
}
Show(results);
Or cache the results of selections
Dictionary<node, IEnumerable<Entity>> _nodeResults; // somewhere
foreach (var node in selectedNodes)
{
if (!_nodeResults.ContainsKey(node))
_nodeResults.Add(node, Session.Query<Entity>().Where(...).Future<Entity>());
results = results.Concat(_nodeResults[node]);
}
if you need distinct results use Intersect instead of Concat or use Show(results.Distinct());
Related
I'm developing a personal frontend for my Media Server that entails the use of Entity Framework Core, and adding the Movies within my Media Server to a database. So far, i've got it working just as I want it to, where I can manually search a film, search TMDB using the API and save the film/studios in my db. What I want to do, however, is have an action called 'Scrape' that will, well, 'scrape' my media server for a list of movies, check if they exist in my db and if not, search these films on TMDB and save them automatically. I've also got this working...kind of.
For example, i'll have a List that will be looped through in the 'Scrape' controller, and this list is a list of movies that need to be searched, so:
Avengers: Infinity War
The Avengers
Tron
Harry Potter
I'm running the list through a foreach() loop, and for each item i'm going through the search procedure, and I can check how many results there are. Now this is where I run into my problem. If the length of the result is more than one, I need the user to be able to search through these results midloop, select a film then have the selected film be added. I'm able to cycle through my List and add all of the films that only have one result, but its the ones that have multiple. For example, 'Tron' is going to return more than one result, and the user needs to determine which version of Tron they wanted to add.
So this is the controller:
List<string> items = NetworkScrape.ScrapeFolders();
foreach (var item in items)
{
//Results from the movie search
SearchContainer<SearchMovie> Results = client.SearchMovieAsync(item).Result;
if (Results.Results.Count == 0)
{
Console.WriteLine(item + " could not be found.");
continue;
}
if (Results.Results.Count == 1)
{
Console.WriteLine(item + " only has one entry, auto add.");
MoviesSelectViewModel vm = new MoviesSelectViewModel
{
TMDBid = Results.Results[0].Id
};
//Add the movie to the DB
await Create(vm);
continue;
}
if (Results.Results.Count > 1)
{
Console.WriteLine(item + " has more than one entry, manual input required.");
//This is where the user would select the film
continue;
}
}
I've only got all of the WriteLine's for testing purposes, and 'items' is the list of movies to search. The final use case down the bottom, if results is more than 1, is where I want to pass 'Results.Results' to a View where the user is shown a table of the search results, in which they can select, but I don't know how to make the foreach loop wait for that result from the view, and even if i could halt the loop i don't exactly know how I can let the loop know when it is okay to 'continue'. I tried await but you can't do that with a View so i'm really lost.
Sorry for the big, long post but I just thought i'd give as much information as I can to help illustrate my problem because i'm totally lost. Any help at all would be appreciated, or even a better way of doing this.
So I'm primarily working with C# and have a method which runs a query that will return x amount of results based on the situation and then set these results as an array "dataGrid". Atm I need a means of creating a method or something which can go through these results in dataGrid then and looking for matching "taskID's" in the taskID columns then take those results and put them into another array called "bindedGrid".
Any ideas? I hope I worded this properly.
I'm working with Visual Studio btw and these SQL query results are coming from an API which we have set up. So the method calls another method in the API which then returns the proper results from the SQL server.
With what should taskID match?
Is the array an array of DataRow objects?
If so, there are three ways of doing this, Lambda, foreach or LINQ
Lambda
var matchings = dataGrid.Where(dr => dr["taskID"].toString() == "matchkey");
foreach
List<DataRow> matchings = new List<DataRow>();
foreach (var dr in dataGrid) {
if (dr["taskID"].toString() === "matchkey")
matchings.add(dr);
}
If you want to join another table, I prefer to use LINQ:
var matchings = from row in dataGrid
join task in Tasks
on row["taskID"].toString() equals Task["ID"]
select row;
Tell me if this is not what you need.
You might need to add using System.Linq; to the top of your file for this to work.
I guess you need to use a foreach loop. Take a look at the official documentation:
https://msdn.microsoft.com/pt-pt/library/ttw7t8t6.aspx
foreach(var item in dataGrid){
//imagine you have 10 "variables" in your array, the "item" will be
the first, then loop and will be the second, etc...and the loop goes
trought all your "variables". here you need to implement your logic,
using the "item" namespace and you will be working with one of those
"variables" at time.
}
I have a Droplist field in an item that contains other items which are under the path /sitecore/content/Home. I need to get the selected item from the Droplist.
In this situation, I have to get the selected Item by its name. Are there any other efficient ways of doing this, or is the way I am doing this okay?
public static Item GetItemByName(string itemName)
{
Database masterDb = Factory.GetDatabase("master");
Item homeItem = masterDb.GetItem("/sitecore/content/Home");
return homeItem.Axes.GetDescendants().FirstOrDefault(p => p.Name == itemName);
}
Droplist is not the luckiest choice here. You should use Droplink instead - it stores the item as ID, instead of storing item name only.
You should avoid using name as item identifier. There can be multiple items with the same name, even under same parent.
homeItem.Axes.GetDescendants() is not really efficient method. It gets all the items which are under that node. You should avoid using it.
If you know that the item will be a child of the homeItem, you can use:
homeItem.Children.FirstOrDefault(p => p.Name == itemName)
If that item can be at any level under the homeItem, you can try to use index to get that item (checking item name equals to specified name and item full path starts with home page full path).
This more of an information note than the answer .. #Marek 's answer is absolutely correct that you should use a DropLink instead so that you address the ID of the item directly.
Never (never! Never!) use GetDescendants in a call such as this (ie from Home downwards).I would try and avoid using it anywhere, ever :) [If i could burn GetDescendants out of the API I would :P]
If you think about it, you are starting at the Home node and then iterating down, visiting every single item as you go and it wont stop until it has touched every item, pulled every item from the DB and interrogated it. On a small dev site this opertation will be fast but as your solution gets bigger and bigger, as content editors create more and more items you will find you solution gets slower and slower and your SQL Server get more and more load (and you likely wont immediately know why !)
If you need to do a larger ranging query (i.e. to check a field on every item under the home node) then you should look at Sitecore's ContentSearch API as this is massively faster for doing these sorts of operations.
As #Stephen Pope mentioned to most efficient way to search for an Item by Name is via the ContentSearch. I recently gave a simple Content Search example which you can modify for your needs by add the following line to so that it searches Sitecore Item Names to find those with a matching name.
IQueryable<SearchResultItem> query = index.GetQueryable<SearchResultItem>().Where(i => i.Name == itemName).Filter(predicate);
It is also worth following #Marek Musielak's advice and using Droplink over Droplist where possible so the value contained in the field is the ID of an Item instead of its Name which is far more useful in your development.
Most of them have given the answers correctly. I would also suggest the same.
Droplink is always preferable to droplist because it stores the item ID instead of name. Droplink will give you a lot of flexibility over droplist.
GetDescendants - Loop through all the items and check so avoid as much as possible.instead use sitecore queries or fast queries which gives you more efficiency.
masterDb.SelectItems("fast:/sitecore/content/Home//*[##templateid = '{F348C2A0-73B8-4AF4-BD9E-2C5901908369}']");
No one is going to store all the items in the same node. You would have created different type of items under home node. If you want to retrieve a specific set of items,Go for sitecore queries instead of getdescendants.
Currently I'm working on a project using LinqtoSql and I would like to get an simpler solution for my current problem.
Example:
Lets say I got a table named Example with three rows (with values 1,2,4)
Now in code(c#) I got these values as a list of Integer(lets name it lstExisting)
Now in my method I got another List of Integer ( say lstCurrent) with Integers values (1,2,3)
Now I want to compare the both the list and find the difference of integers and update the database, so according to my example a new row with value 3 should be added and the existing row with value 4 should be deleted.
PS:(the integer values will be always unique and will be 1,2,3,4)
Linq solutions will be preferable but I don't mind other easier solutions.
Thanks
You need to find new items and to be deleted items using Except like:
var newItems = lstCurrent.Except(lstExisting).ToList();
var toBeDeletedItems = lstExisting.Except(lstCurrent).ToList();
Later you can iterate each list and Add/Delete accordingly.
Try using Contains(). With having two lists, you can write something like this. What this does is it iterates over each item in your methods list and checks the original to see if its there.
var lstExisting = getExistingList();
var lstCurrent = getCurrentList();
foreach(var currentInt in lstCurrent)
{
if(!lstExisting.Contains(currentInt))
{
//insert currentInt
}
What could be the best preferable way of returning back a modified list grabbed from an Entity Framework to our database.
Question In a simpler form :
How to return a Custom List e.g List of about 100,000 records to the database
these are the modified version of our entities in an offline Thread-safe manner.
The Code :
var query = From context.Products
select p;
var listQuery = query.ToList();
Edit : Seems that all the attached Lists to Entities will cause Thread-Safety errors.
So we have to make a cloned version of the list, something like List
and after edition insert all the items in a regular time-consuming or a shorthand way,
Any Ideas ?
Sample Steps :
Make and fill an Custom List Array of our defined type from an entity DataContext
Iterate through the List ( about 100,000 items)
Edit the List
Finally Return it back to the database
How to pass listQuery to the database ?
Iterating through each of them and find the equivalent entity or record via Entity/Linq and change the item ?? could it be the best idea or do we have any shorthand or best practice doing this ?
Any suggestion or idea ?
First, there is a slight error in your code example. You need to add 'from p in context.Products' rather than 'from context.Products'
If I am understanding correctly, the way i typically edit a list of records is:
var products = dbContext.Products.ToList(); // Gets As List
foreach (var product in products)
{
// edit the value, EF manages what is changed
product.someField = "some new value";
}
dbContext.SaveChanges(); // Saves All Changes
I prefer to use method syntax. If you prefer to use query syntax, you can replace the first line with:
var products = (from p in products
select p).ToList();