Unable to Save List<dynamic> using Rob Conery's Massive - c#

I'm using Rob Conery's Massive to connect to my database, but I don't seem to be able to be able to save a list of dynamic objects to the database. I thought this was supported though.
Here's the code I am attempting to use:
int numberOfChildren = int.Parse(Request.Form["numberOfChildren"]);
List<dynamic> children = new List<dynamic>();
for(int i = 1; i <= numberOfChildren; i++) {
dynamic child = new ExpandoObject();
child.FamilyID = familyId;
child.Type = "CHILD";
child.LastName = Request.Form[i + "-childLastName"];
child.FirstName = Request.Form[i + "-childFirstName"];
child.SendSmsAlerts = false;
child.Gender = Request.Form[i + "-childGender"];
child.Birthdate = Request.Form[i + "-childBirthdate"];
children.Add(child);
}
var people = new People();
people.Save(children);
I get a "Parameter count mismatch." error on line 78 of Massive.cs
Everything works fine if i only pass in a single dynamic object at a time, the error is only raised when I attempt to pass in the list. Based on the documentation on GitHub I thought this was supported and it would save all the children in one transaction.

Save takes an params array not a list.
people.Save(children.ToArray());

Related

Sitefinity: Dynamic Content query optimization with field values

I will attempt to be as specific as possible. So we are using Sitefinity 8.1.5800, I have a couple dynamic content modules named ReleaseNotes and ReleaseNoteItems. ReleaseNotes has some fields but no reference to ReleaseNoteItems.
Release Note Items has fields and a related data field to ReleaseNotes.
So I can query all ReleaseNoteItems as dynamic content pretty quickly less than a second.
I then use these objects provided by sitefinity and map them to a C# object so I can use strong type. This mapping process is taking almost a minute and using over 600 queries for only 322 items (N+1).
In Short: I need to get all sitefinity objects and Map them to a usable c# object quicker than I currently am.
The method for fetching the dynamic content items (takes milliseconds):
private IList<DynamicContent> GetAllLiveReleaseNoteItemsByReleaseNoteParentId(Guid releaseNoteParentId)
{
DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(String.Empty);
Type releasenoteitemType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.ReleaseNoteItems.Releasenoteitem");
string releaseNoteParentTypeString = "Telerik.Sitefinity.DynamicTypes.Model.ReleaseNotes.Releasenote";
var provider = dynamicModuleManager.Provider as OpenAccessDynamicModuleProvider;
int? totalCount = 0;
var cultureName = "en";
Thread.CurrentThread.CurrentUICulture = new CultureInfo(cultureName);
Type releasenoteType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.ReleaseNotes.Releasenote");
// This is how we get the releasenote items through filtering
DynamicContent myCurrentItem = dynamicModuleManager.GetDataItem(releasenoteType, releaseNoteParentId);
var myMasterParent =
dynamicModuleManager.Lifecycle.GetMaster(myCurrentItem) as DynamicContent;
var relatingItems = provider.GetRelatedItems(
releaseNoteParentTypeString,
"OpenAccessProvider",
myMasterParent.Id,
string.Empty,
releasenoteitemType,
ContentLifecycleStatus.Live,
string.Empty,
string.Empty,
null,
null,
ref totalCount,
RelationDirection.Parent).OfType<DynamicContent>();
IList<DynamicContent> allReleaseNoteItems = relatingItems.ToList();
return allReleaseNoteItems;
}
This is the method that takes almost a minute that is mapping sitefinity object to C# object:
public IList<ReleaseNoteItemModel> GetReleaseNoteItemsByReleaseNoteParent(ReleaseNoteModel releaseNoteItemParent)
{
return GetAllLiveReleaseNoteItemsByReleaseNoteParentId(releaseNoteItemParent.Id).Select(rn => new ReleaseNoteItemModel
{
Id = rn.Id,
Added = rn.GetValue("Added") is bool ? (bool)rn.GetValue("Added") : false,
BugId = rn.GetValue<string>("bug_id"),
BugStatus = rn.GetValue<Lstring>("bugStatus"),
Category = rn.GetValue<Lstring>("category"),
Component = rn.GetValue<Lstring>("component"),
#Content = rn.GetValue<Lstring>("content"),
Criticality = rn.GetValue<Lstring>("criticality"),
Customer = rn.GetValue<string>("customer"),
Date = rn.GetValue<DateTime?>("date"),
Grouped = rn.GetValue<string>("grouped"),
Override = rn.GetValue<string>("override"),
Patch_Num = rn.GetValue<string>("patch_num"),
PublishedDate = rn.PublicationDate,
Risk = rn.GetValue<Lstring>("risk"),
Title = rn.GetValue<string>("Title"),
Summary = rn.GetValue<Lstring>("summary"),
Prod_Name = rn.GetValue<Lstring>("prod_name"),
ReleaseNoteParent = releaseNoteItemParent,
McProductId = GetMcProductId(rn.GetRelatedItems("McProducts").Cast<DynamicContent>()),
}).ToList();
}
Is there any way to optimize this all into one query or a better way of doing this? Taking almost a minute to map this objects is too long for what we need to do with them.
If there is no way we will have to cache the items or make a SQL query. I would rather not do caching or SQL query if I do not have to.
Thank you in advance for any and all help you can provide, I am new to posting questions on stackoverflow so if you need any additional data please let me know.
Is there a reason why you are doing a .ToList() for the items? Is it possible for you to avoid that. In my opinion, most of the time(of the 1 minute) is taken to convert all your items into a list. Conversion from Sitefinity object to C# object is not the culprit here.
Look Arno's answer here: https://plus.google.com/u/0/112295105425490148444/posts/QrsVtxj1sCB?cfem=1
You can use the "Content links manager" to query dynamic modules relationships (both by parent -ParentItemId- or by child -ChildItemId-) much faster:
var providerName = String.Empty;
var parentTitle = "Parent";
var relatedTitle = "RelatedItem3";
DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(providerName);
Type parentType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.ParentModules.ParentModule");
Type relatedType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.RelatedModules.RelatedModule");
ContentLinksManager contentLinksManager = ContentLinksManager.GetManager();
// get the live version of all parent items
var parentItems = dynamicModuleManager.GetDataItems(parentType).Where(i => i.GetValue<string>("Title").Contains(parentTitle) && i.Status == ContentLifecycleStatus.Live && i.Visible);
// get the ids of the related items.
// We use the OriginalContentId property since we work with the live vesrions of the dynamic modules
var parentItemIds = parentItems.Select(i => i.OriginalContentId).ToList();
// get the live versions of all the schedules items
var relatedItems = dynamicModuleManager.GetDataItems(relatedType).Where(i => i.Status == ContentLifecycleStatus.Live && i.Visible && i.GetValue<string>("Title").Contains(relatedTitle));
// get the content links
var contentLinks = contentLinksManager.GetContentLinks().Where(cl => cl.ParentItemType == parentType.FullName && cl.ComponentPropertyName == "RelatedField" && parentItemIds.Contains(cl.ParentItemId) && cl.AvailableForLive);
// get the IDs of the desired parent items
var filteredParentItemIds = contentLinks.Join<ContentLink, DynamicContent, Guid, Guid>(relatedItems, (cl) => cl.ChildItemId, (i) => i.OriginalContentId, (cl, i) => cl.ParentItemId).Distinct();
// get the desired parent items by the filtered IDs
var filteredParentItems = parentItems.Where(i => filteredParentItemIds.Contains(i.OriginalContentId)).ToList();
I would imagine that every release note item under a single release note would be related to the same product wouldn't it?
If so, do you need to do the GetMcProductId method for every item?

Couchbase Bulk loading error with upsert() (.NET SDK 2.0)

I have encountering an error when inserting bulk data with the upsert function and cannot figure out how to fix it. Anyone know what is wrong here? What the program is essentially doing is grabbing data from a SQL server database and loading into our Couchbase bucket on an Amazon instance. It does initially begin loading but after about 10 or so upserts it then crashes.
My error is as follows:
Collection was modified; enumeration operation may not execute.
Here are the screen shots of the error (Sorry the error only is replicated on my other Amazon server instance and not locally):
http://imgur.com/a/ZJB0c
Here is the function which is calling the upsert method. This is called multiple times since I'm retrieving only parts of the data at a time since the SQL table is very large.
private void receiptItemInsert(double i, int k) {
const int BATCH_SIZE = 10000;
APSSEntities entity = new APSSEntities();
var data = entity.ReceiptItems.OrderBy(x => x.ID).Skip((int)i * BATCH_SIZE).Take(BATCH_SIZE);
var joinedData = from d in data
join s in entity.Stocks
on new { stkId = (Guid)d.StockID } equals new { stkId = s.ID } into ps
from s in ps.DefaultIfEmpty()
select new { d, s };
var stuff = joinedData.ToList();
var dict = new Dictionary<string, dynamic>();
foreach (var ri in stuff)
{
Stock stock = new Stock();
var ritem = new CouchModel.ReceiptItem(ri.d, k, ri.s);
string key = "receipt_item:" + k.ToString() + ":" + ri.d.ID.ToString();
dict.Add(key, ritem);
}
entity.Dispose();
using (var cluster = new Cluster(config))
{
//open buckets here
using (var bucket = cluster.OpenBucket("myhoney"))
{
bucket.Upsert(dict); #CRASHES HERE
}
}
}
as discussed in the Couchbase Forums, this is probably a bug in the SDK.
When initializing the internal map of the couchbase cluster, the SDK will construct a List of endpoints. If two+ threads (as is the case during a bulk upsert) trigger this code at the same time, one may see an instance of the List being populated by the other (because the lock is entered just after a call to List.Any(), which may crash if the list is being modified).

The best way to pass rows of an SQL Database to Javascript?

So, recently I've been looking into the HTML5 Indexeddb feature which is controlled with Javascript, and how to incorporate this with an SQL Server database to share and copy information across so that a version of the database is available offline.
The conundrum that I have is finding the best way to pass a set of objects from an SQL Server database through to the javascript of a browser, using C# to get the values from the database.
Though there are many little "hacks" that can be done (e.g Putting data into labels and then having the Javascript just pick it up document.getElementById("DataHere").value;) I was wondering if there were more efficient ways of passing the contents of a database across?
At the moment I have a method that generates an array of strings (all in the JSON format, using the JSON.Net package) as an example of what would be returned from the database.
public string[] GenerateEmployeeSample() {
List<Employee> listEmps = new List<Employee>();
string[] listJSON = new string[64];
string[] FirstNames = {"Alonso", "Alfred", "Angus", "Alfresco" };
string[] LastNames = {"Johnson","Williams", "Zelwegger", "Jones" };
string[] Departments = {"Finance", "Cleaning", "Pusher", "Stairs" };
string emailEnd = "#email.com";
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
for (int k = 0; k < 4; k++) {
Employee tempEmp = new Employee();
tempEmp.FirstName = FirstNames[i];
tempEmp.LastName = LastNames[j];
tempEmp.Department = Departments[k];
tempEmp.Email = FirstNames[i] + "." + LastNames[j] + emailEnd;
listEmps.Add(tempEmp);
}
}
}
int count = 0;
foreach(Employee emp in listEmps){
string tempString = JsonConvert.SerializeObject(emp);
listJSON[count] = tempString;
count++;
}
return listJSON;
}
So now I have a set of data, how would I be able to pass this array through to Javascript?
I apologise if this is a trivial question but Javascript is still rather new to me, and after reading through quite a few examples that either didn't do what I wanted or just outright didn't work I am at a bit of a loss.
Thanks very much for reading!
To be more specific, you would make a resource (be it an aspx page or or a json file etc) that returns a JSON string when requested. You're already partway there with this step, because you've already got the code for serializing objects as JSON. A simple way of doing this would be to have a page that outputs the return value of this function using Response.Write(GenerateEmployeeSample());
Then you would use the XMLHttpRequest object to request this resource, and parse the returned JSON using javascript's JSON.parse, which returns a native javascript object. You may then do with this object as you please.

How does paging work on the C# Facebook sdk

Cannot find any documentation for this...
Currently using the following code to get a list of my photos:
FacebookApp fb = new FacebookApp(accessToken);
dynamic test = fb.Get("me/photos");
I'm cycling through the first 25 photos that it returns. Simple.
Now how do it get it to return the next 25?
So far I've tried this:
FacebookApp fb = new FacebookApp(accessToken);
string query = "me/photos";
while (true)
{
dynamic test = fb.Get(query);
foreach (dynamic each in test.data)
{
// do something here
}
query = test.paging.next;
}
but it fails throwing:
Could not parse '2010-08-30T17%3A58%3A56%2B0000' into a date or time.
Do I have to use a fresh dynamic variable for every request, or am I going about this the wrong way completely?
Ended up finding this:
// first set (1-25)
var parameters = new ExpandoObject();
parameters.limit = 25;
parameters.offset = 0;
app.Api("me/friends", parameters);
// next set (26-50)
var parameters = new ExpandoObject();
parameters.limit = 25;
parameters.offset = 25;
app.Api("me/friends", parameters);
I also found you can use this.
// for the first 25 albums (in this case) 1-25
dynamic albums = client.Get("me/albums", new { limit = "25", offset = "0"});
// for the next 25 albums, 26-50
dynamic albums = client.Get("me/albums", new { limit = "25", offset = "25"});
Worked the same as you used above.

Build dynamic list c#

This code works correctly to make a web service call:
int numberOfGuests = Convert.ToInt32(search.Guest);
var list = new List<Guest>();
Guest adult = new Guest();
adult.Id = 1;
adult.Title = "Mr";
adult.Firstname = "Test";
adult.Surname = "Test";
list.Add(adult);
Guest adult2 = new Guest();
adult2.Id = 2;
adult2.Title = "Mr";
adult2.Firstname = "Test";
adult2.Surname = "Test";
list.Add(adult2);
Guest[] adults = list.ToArray();
How do I build the list dynamically using the numberofguests variable to create the list? The output has to match the output shown exactly else the web service call fails, so adult.id = 1, adult2.id = 2, adult3.id = 3, etc...
Do you know about loops?
for (int i = 1; i <= numberofGuests; i++) {
var adult = new Guest();
adult.Id = i;
adult.Title = "Mr";
adult.Firstname = "Test";
adult.Surname = "Test";
list.Add(adult)
}
This runs the code within the loop once from 1 to numberOfGuests, setting the variable i to the current value.
The Linq way :-)
var list = (from i in Enumerable.Range(1, numberOfGuests)
select new Guest
{
Id = i,
Title = "Mr.",
Firstname = "Test",
Surname = "Test"
}).ToList();
You need a for loop. Or, better yet, a decent C# book -- these are really basics of C#.
Are you asking how to display a list dynamically? I'm not really sure what the question here is about, as the other answers say if you know the value of numberofGuests then you can just use a loop to go through your list.
I suspect you are wondering how to obtain this information in the first place, am I right? If you want to dynamically add controls to a page (your previous post suggest this was ASP.Net I think?), so that you only display the correct number of controls then take a look at these related questions:
Dynamically adding controls in ASP.NET Repeater
ASP.NET - How to dynamically generate Labels

Categories