Umbraco: Update Property on specific member - umbraco

I'm running a forum with Umbraco 7, and I wish to update a property on a specific member by hes Id.
This is what I tried:
var authorId = Model.Content.GetPropertyValue<int>("postAuthor", 0);
var author = Members.GetById(authorId);
umbraco.cms.businesslogic.member.Member member = umbraco.cms.businesslogic.member.Member.GetMemberFromEmail(author.GetPropertyValue("email").ToString());
member.getProperty("postCounter").Value = Convert.ToInt32(member.getProperty("postCounter")) + 1;
member.Save();
But this dont work and the line below throws this error:
umbraco.cms.businesslogic.member.Member member = umbraco.cms.businesslogic.member.Member.GetMemberFromEmail(author.GetPropertyValue("email").ToString());
It says: Warning: umbraco.cms.businesslogic.member.Member is obsolete: "Use the MemberService and the Umbraco.Core.Models.Member models instead"
Can someone help me solve this?

var memberService = ApplicationContext.Current.Services.MemberService
var member = memberService.GetById(authorId)
member.SetValue("postCounter", newValue);
memberService.Save(member);
Never, ever do this though!!
You need to store counts like this that update really frequently in your own separate table as each time you save a piece of content (and yes, the member object is basically a piece of content as well) you will save a new version in the versions table. All of your custom properties will also be saved again with the new version. Also this is a fairly database-intense operation which is completely unnecessary, just have a table with two columns: the memberId and the count and you're done and it's all very lean and performant.

If you are in razor script you want to do something like:
var authorId = Model.Content.GetPropertyValue<int>("postAuthor", 0);
var ms = ApplicationContext.Current.Services.MemberService;
var member = ms.GetById(authorId);
member.SetValue("postCounter",member.GetValue("postCounter"));
But as sebastian says you probably want to do it differently for performance

Related

Update method not doing anything to a document - can't understand why

I'm a total beginner working through an entry-level university course on data handling. I've been tasked with building a simple database app that the user can add movies to and then mark them "watched". I have a "watch a movie" function (source below) that needs to prompt the user for the name of the movie and then mark that particular movie as "watched". The function receives a movie collection from a database as its single parameter, and the collection only contains the name and watched status for each movie.
Now what happens is the update method on the last line doesn't do anything, and I can't figure out why. I've tested it by including a print command right after the update command, but the document is unchanged. I even tried updating the name of the movie at the same time, but no change.
Any ideas?
watch(collection) async {
print('Name of the movie?');
var name = stdin.readLineSync();
var terms = Query(filter: ValueFilter({'name': name}));
var results = await collection.search(query: terms);
var documents = results.snapshots;
for (var i = 0; i < documents.length; i++) {
var data = documents[i].data;
var document = documents[i].document;
document.update(data: {'name': data['name'], 'watched': true});
}
}
OK, so I had help and managed to solve this. I don't know why, but the ValueFilter needed a MapFilter around it, i.e.
var haku = Query(filter: MapFilter({'nimi': ValueFilter(nimi)}));
It works now, but if anyone could explain why, I'd appreciate it. :D

Use Content instead of Document in Umbraco (v6)

I would like to update some obsolete code from umbraco v4 in the updated to v6 solution.
I have
entitiesFolder = new umbraco.cms.businesslogic.web.Document(folderId);
entitiesFolder.ReorderChildren(
entitiesFolder.Children.OrderBy(fdoc => fdoc.Text),
refreshEntireCache);
Now the recomendation instead of obsolete Document is to use Umbraco.Core.Models.Content. How? Didn't find (as usual for Umbraco) any documentation about... (
// new version
var toto = new Umbraco.Core.Models.Content(??)
toto.SoirtChildren(???)
Are you doing this from a razor view? If so you can do:
var nodeId = 123;
var myNode = Umbraco.TypedContent(nodeId);
var property = myNode.GetPropertyValue<string>("myStringAlias");
If you're doing it from a class or something you'll have to use something like:
var helper = new UmbracoHelper(UmbracoContext.Current);
var nodeId = 123;
var myNode = helper.TypedContent(nodeId);
(This is untested but it should work..)
If you are just querying data and need to sort it, using the umbracoHelper is a great way to go. It only hits the xml cache in App_Data/umbraco.config, so you don't hit the database.
However, if you are attempting to programatically sort some of the nodes in the content tree, you will need to use the ContentService. You will need to use the ContentService whenever you actually want to programatically modify content nodes. You will also find a similar MediaService for media.
https://our.umbraco.org/Documentation/Reference/Management-v6/Services/ContentService
ApplicationContext.Current.Services.ContentService.Sort(...)

How to use Slickgrid Formatters with MVC

I am working on a first Slickgrid MVC application where the column definition and format is to be stored in a database. I can retrieve the list of columns quite happily and populate them until I ran into the issue with formatting of dates. No problem - for each date (or time) column I can store a formatter name in the database so this can be retrieved as well. I'm using the following code which works ok:
CLOP_ViewColumnsDataContext columnDB = new CLOP_ViewColumnsDataContext();
var results = from u in columnDB.CLOP_VIEW_COLUMNs
select u;
List<dynColumns> newColumns = new List<dynColumns>();
foreach(CLOP_VIEW_COLUMN column in results)
{
newColumns.Add(new dynColumns
{
id = column.COLUMN_NUMBER.ToString(),
name = column.HEADING.Trim(),
field = column.VIEW_FIELD.Trim(),
width = column.WIDTH,
formatter = column.FORMATTER.Trim()
});
}
var gridColumns = new JavaScriptSerializer().Serialize(newColumns);
This is all fine apart from the fomatter. An example of the variable gridColumns is:
[{"id":"1","name":"Date","field":"SCHEDULED_DATE","width":100,"formatter":"Slick.Formatters.Date"},{"id":"2","name":"Carrier","field":"CARRIER","width":50,"formatter":null}]
Which doesn't look too bad however the application the fails with the error Microsoft JScript runtime error: Function expected in the slick.grid.js script
Any help much appreciated - even if there is a better way of doing this!
You are assigning a string to the formatter property, wich is expected to be function.
Try:
window["Slick"]["Formatters"]["Date"];
But i really think you should reconsider doing it this way and instead store your values in the db and define your columns through code.
It will be easier to maintain and is less error prone.
What if you decide to use custom editors and formatters, which you later rename?
Then your code will break or you'll have to rename all entries in the db as well as in code.

Returning Updated Results from DBSet.SqlQuery

I want to use the following method to flag people in the Person table so that they can be processed. These people must be flagged as "In Process" so that other threads do not operate on the same rows.
In SQL Management Studio the query works as expected. When I call the method in my application I receive the row for the person but with the old status.
Status is one of many navigation properties off of Person and when this query returns it is the only property returned as a proxy object.
// This is how I'm calling it (obvious, I know)
var result = PersonLogic.GetPeopleWaitingInLine(100);
// And Here is my method.
public IList<Person> GetPeopleWaitingInLine(int count)
{
const string query =
#"UPDATE top(#count) PERSON
SET PERSON_STATUS_ID = #inProcessStatusId
OUTPUT INSERTED.PERSON_ID,
INSERTED.STATUS_ID
FROM PERSON
WHERE PERSON_STATUS_ID = #queuedStatusId";
var queuedStatusId = StatusLogic.GetStatus("Queued").Id;
var inProcessStatusId = StatusLogic.GetStatus("In Process").Id;
return Context.People.SqlQuery(query,
new SqlParameter("count", count),
new SqlParameter("queuedStateId", queuedStateId),
new SqlParameter("inProcessStateId", inProcessStateId)
}
// update | if I refresh the result set then I get the correct results
// but I'm not sure about this solution since it will require 2 DB calls
Context.ObjectContext().Refresh(RefreshMode.StoreWins, results);
I know it is an old question but this could help somebody.
It seems you are using a global Context for your query, EF is designed to retain cache info, if you allways need fresh data must use a fresh context to retrieve it. as this:
using (var tmpContext = new Contex())
{
// your query here
}
This create the context and recycle it. This means no cache was stored and next time it gets fresh data from database not from cache.

Problem creating an Entity object/queryable from the result of a LINQ join in MVC

I'm attempting to write a search function for a database table that needs to access information from related tables using Entity Framework. However, I'm running into problems getting the data back out of my initial query after doing a join on the parent table and the related tables. My code currently looks like this. I initialize my queryable object
IQueryable<PurchaseOrder> po = _context.PurchaseOrders;
Where PurchaseOrder is an Entity type. Then there is a series of blocks like this.
if (!String.IsNullOrEmpty(searchViewModel.Comment)){
var helper = _context.PurchaseOrderComments.Where(x => x.CommentText.Contains(searchViewModel.Comment));
var mid = po.Join(helper, r => r.PurchaseOrderID, u => u.PurchaseOrderID, (r, u) =>
new
{
PurchaseOrderID = r.PurchaseOrderID,
PurchaseOrderNumber = r.PurchaseOrderNumber,
VendorID = r.VendorID,
ContractNumber = r.ContractNumber,
BuyerUserID = r.BuyerUserID
});
po = mid.Select(x => new PurchaseOrder
{
PurchaseOrderID = x.PurchaseOrderID,
PurchaseOrderNumber = x.PurchaseOrderNumber,
VendorID = x.VendorID,
ContractNumber = x.ContractNumber,
BuyerUserID = x.BuyerUserID
});
}
After each block, po is passed to the next search parameter. However, as you might guess, my program complains that I can't build a complex type in mid's Select statement. I've also tried building PurchaseOrder objects from the contents of mid, inserting them into a new List of PurchaseOrders, and converting that list into a queryable to assign to po to pass on to the next block. However, that changes po's data type from System.Data.Object.ObjectSet to System.Collections.Generic.List, which then throws an InvalidOperationException the next time I try and iterate through it using a foreach.
So my question is, are there any obvious mistakes in my approach or any suggestions for other ways to approach the problem? Thanks very much for any help.
I think you're making this more complicated than it needs to be. If I understand what you're trying to do, you should be able to do something like this:
if (!String.IsNullOrEmpty(searchViewModel.Comment)){
po = po.Where(
o => o.PurchaseOrderComments.Any(
c => c.CommentText.Contains(searchViewModel.Comment)));
}
StriplingWarrior's solution is the best way. In case that your PurchaseOrder class really doesn't have a navigation collection of PurchaseOrderComments (which would force you to use a join) the following should work and is simpler as your double projection:
po=po.Join(helper, r => r.PurchaseOrderID, u => u.PurchaseOrderID, (r, u) => r);

Resources