TreeView using MVC 3 with Razor Engine - asp.net

I have a unique sql database setup in which I'm using nested sets to determine the hierarchy. Here's an example of it:
HierarchyID = 1, HierarchyText = "Contract", HierarchyLeft = 1,
HierarchyRight = 54
HierarchyID = 2, HierarhcyText = "Part 1...", HierarchyLeft = 2, HierarchyRight = 41
HierarchyID = 3, HierarchyText = "Part 2...", HierarchyLeft = 42,
HierarchyRight = 45
HierarchyID = 8, HierarchyText = "General Provisions",
HierarchyLeft = 3, HierarchyRight = 40
The idea is that the children (or subcategories) are contained within the parent's LEFT and RIGHT values. So, for instance, "General Provisions" is a child of "Part 1..." which is a child of "Contract". "Part 1..." and "Part 2" are siblings of each other since they don't contain each other going by the left and right values.
The question I have is this: Is there a way to use MVC3 with Razor Engine to create a tree and display it pulling from this database? The only examples I've seen have been databases that have each node in the database pointing to its parent. If it's possible, could you provide sample code for the CONTROLLER and VIEW? I'd appreciate that. Also, I'm able to pull the hierarchy names by level. So, I'd appreciate an example in which I could feed the tree control a level at a time. For instance, feed the top level... when the user clicks on it, feed the next leve, etc. down the tree. I would really appreciate any help!

You seem to be using the Nested Set Model to define hierarchical data. Personally I would use recursive display templates once the data is fetched from the database into a view model to display the tree. Here's an example in which I illustrated similar concepts in action which you could adapt to meet your specific requirements.

Related

Google Datastore deletes and multiple parents

I have a data model in which entity A contains references to two other entities, B and C. If either B or C is deleted, I want A to be deleted.
When creating A, it's possible to name either B or C as its parent. Is it also possible to name both B and C as its parents so that if either B or C is deleted, A is also deleted?
In more concrete terms, say search results, a result might have both a category and a region, say a web page about birds in North America. The result is stored with a reference to its category and region. Later, you want to delete the category birds and you want the result also deleted. Likewise, you delete the region North America and want the result deleted.
I hate to go on at such length about such a trivial scenario. But it doesn't seem to be covered in any of the Datastore documentation. What am I missing? Is it a basically flawed data model?
Single-parent limitation:
A child can have only one parent in Datastore. In other words, A can only be a child of B OR C, not both. Of course, a parent can have multiple children, though.
Alternative:
You can use a KeyProperty with repeated=True argument and store many Entity keys on it. In Python, this would be like this:
class A(ndb.Model):
associated_with = ndb.KeyProperty(repeated=True)
some_other_property = ndb.StringProperty()
a_entity = A(
associated_with = [b_key, c_key],
some_other_property = 'any value'
)
a_entity.put()
Automatically triggering deletes:
Datastore doesn't offer this functionality out of the box, but you can mimic it in your application. Just one idea for implementing in Python, for example, you could extend the Model class with your own delete method (haven't tested this code, it's just for illustration):
class A(ndb.Model):
associated_with = ndb.KeyProperty(repeated=True)
some_other_property = ndb.StringProperty()
def delete_ext(entity): # entity object
if entity.associated_with:
for associated in entity.associated_with:
associated.delete()
entity.key.delete()
You may want to wrap all the deletes in a transaction. Beware that a single transaction can operate on up to 25 entity groups.

CouchDB: Merging Objects in Reduce Function

I'm new to CouchDB, so bear with me. I searched SO for an answer, but couldn't narrow it down to this specifically.
I have a mapper function which creates values for a user. The users have seen different product pages, and we want to tally the type and products they've seen.
var emit_values = {};
emit_values.name = doc.name;
...
emit_values.productsViewed = {};
emit_values.productsViewed[doc.product] = 1
emit([doc.id, doc.customer], emit_values);
In the reduce function, I want to gather different values into that productsViewed object for that given user. So after the reduce, I have this:
productsViewed: {
book1: 1,
book3: 2,
book8: 1
}
Unfortunately, doing this creates a reduce overflow error. According to the other posts, this is because the productsViewed object is growing in size in the reduce function, and Couch doesn't like that. Specifically:
A common mistake new CouchDB users make is attempting to construct complex aggregate values with a reduce function. Full reductions should result in a scalar value, like 5, and not, for instance, a JSON hash with a set of unique keys and the count of each.
So, I understand this is not the right way to do this in Couch. Does anyone have any insight into how to properly gather values into a document after reduce?
You simple build a view with the customer as key
emit(doc.customer, doc.product);
Then you can call
/:db/_design/:name/_view/:name?key=":customer"
to get all products an user has viewed.
If a customer can have viewed a product several times you can build a multi-key view
emit([doc.customer, doc.product], null);
and reduce it with the built-in function _count
/:db/_design/:name/_view/:name?startkey=[":customer","\u0000"]&endkey=[":customer","\u9999"]&reduce=true&group_level=2
You have to accept that you cannot
construct complex aggregate values
with CouchDB by requesting the view. If you want to have a data structure like your wished payload
productsViewed: {
book1: 1,
book3: 2,
book8: 1
}
i recommend to use an _update handler on the customer doc. Every request that logs a product visit adds a value to the customer.productsViewed property instead of creating a new doc.

Domino method ViewNavigator createViewNavFromCategory(String categoryName) returns navigator with no entries when used with many sub categories

I have a java servlet that works as a REST service. My data is delivered through a categorized view with 3 categorized columns.
I create a view navigator using the View.createViewNavFromCategory("2014\43") where the category specified adheres to the first two categorized columns.
2014 = year and 43 = week number, which means there can be up to 53 second column categories.
My categorized columns are sorted decending. For some strange reason I found that all columns had to be sorted the same way (undocumented).
My code:
String viewCategory = "";
if (isYearSpecified) viewCategory = <year parameter>;
if (isWeekSpecified) viewCategory = viewCategory + "\\" + <week parameter>;
ViewNavigator nav = lookupView.createViewNavFromCategory(viewCategory);
//and set the size of the preloading cache:
nav.setBufferMaxEntries(numCacheEntries);
// Initialize list of JSON income objects
List prognosisJSON = new ArrayList();
//and then traverse the view:
ViewEntry currEntry = nav.getFirst();
This works as a charm until I specify a week lower than 13. If using category "2014\12", "2014\11" and lower the viewEntry returns null when trying to access the first entry in the navigator.
I should perhaps add that my view contains 2102 documents in categories before the one that fails (if there is an undocumented max limit).
What can I do to prevent this?
I suspect you're hitting this problem http://www.intec.co.uk/apparent-java-getalldocumentsbykey-getallentriesbykey-bug/. The fact it works in LotusScript and the keys you're looking for sound suspicious. To completely confirm it, it should also fail in a Java agent.
The latest I had was that this was planned for 9.0.2.
If so, in the mean time, changing the columns to text instead of number will solve the problem.

I need to group and summarize flat arraycollection data. Data cannot be grouped out side of app and must return arraycollection

I have flat data in my app which I will need to group, summarize, and count as I normally would with a sql query. For this project though, it must be done in the flex app. I need to figure out how to group my data by day or month using a datatime field in my Arraycollection, then appropriately count or summarize data in other fields. I've used Groupingcollections before, but only when binding to hierarchical controls (like AdvancedDataGrid and Tree), but I need a resulting ArrayCollection with the grouped and summarized data.
Basically, I'm trying to access my AC like a sql table (GROUP BY MONTH(datetime), COUNT, COUNT(DISTINCT(), etc.) and I'm unsure how to do it. Does anyone have experience doing this?
You can give ActionLinq (https://bitbucket.org/briangenisio/actionlinq/wiki/Home) a try.
I've not used it myself, but I've been itching to give it a try :)
It's an implementation of Linq (from C#) in actionscript. This gives you a functional way of dealing with collections of data in a very SQL-like manner (select, group, filter, etc.).
I would characterise it like the filter method on steroids.
Here is an example from the website - it shows some of the SQL-like names and how the chaining works:
var transformed:Array =
[-4, -3, -2, -1, 0, 1, 2, 3, 4]
.where(isEven)
.select(square)
.distinct()
.reverse()
.toArray();
assertThat(transformed, array(0, 4, 16));
More information and examples here:
http://riarockstars.com/2011/02/07/processing-data-on-the-clientactionlinq/
You may find that this example points you in the right direction http://flexdiary.blogspot.com/2008/09/groupingcollection-example-featuring.html

Multi-View Search Form (ASP.NET MVC 2)

I have a requirement to build a "Search" form for a travel company. This search form will be used for searching different travel components such as Flights, Hotels, Cars etc.
Most of the fields in the form are common (such as travel dates, origin and destination cities etc) for all components but will also contain some component specific fields (such as Business/First/Economy Class & Nonstop Flight Indicators for Flight Search).
Even though most of the fields are common, they need to be displayed with component-specific labels...for example: "travel dates" would say "check-in & check-out dates" on Hotel search form where as they would say "departure & return dates" on Flight search form.
What is the best approach to design a search form which would display field with component-specific labels and also provides a way to map/associate fields to components (common fields to all component types and component-specific fields to corresponding component)? Is there something similar to Data Annotations for achieving this behavior?
So Within "Form A", field 1 has a certain display label
A "Form" has many fields and each field has a display label that changes by form.
A Form has one or more fields
Not all forms need to have all fields (that is some forms may have fewer fields than the set of all fields).
So if you can imagine a set of tables in a database (the data from these tables can be cached in memory if need be) that represent this data then at the time of rendering a specific form, you'll get the set of fields and their display labels. It's easy enough to then bind the display labels to the appropriate components.
This is the best way to do it rather than rely on reflection.
The basic data structure would be a Dictionary that uses the form's name (or some other identifier) as the key. The "value" part of the Disctionary will be another dictionary that uses the control id/name as the key and the value will be the display label.
so something like:
Dictionary<string, Dictionary<string, string>>
Or you could have a "custom" dictionary for the latter like so
public class
ControlDisplayLabelDictionary :
Dictionary {
}
And then you could populate the whole structure like so:
var formControlLabels = new Dictionary<string,
ControlDisplayLabelDictionary>();
var cdForFormA = new ControlDisplayLabelDictionary();
cdForFormA.Add("Control1", "Travel Dates");
cdForFormA.Add("Control2", "Some Label control2 on FormA");
cdForFormA.Add("Control3", "Some Label control3 on FormA");
formControlLabels.Add("Form A", cdForFormA);
var cdForFormB = new ControlDisplayLabelDictionary();
cdForFormA.Add("Control1", "Booking Dates");
cdForFormA.Add("Control2", "Some Label control2 on FormB");
cdForFormA.Add("Control3", "Some Label control3 on FormB");
formControlLabels.Add("Form B", cdForFormA);
Of course, when the data comes from a database the actual population code will differ but the idea remains the same. Now you could choose the cache this structure in memory but I wouldn't do that unless there is a performance issues since the database will actually cache this "data" in memory anyway and it is very unlikely that the database engine will hit the hard disks after the first time. Provided of course you have enough memory on your database server box.

Resources