Adding associative document _id to user.profile key in Accounts.onCreateUser() - function

I am trying to insert a document id into the user.profile key when in Accounts.onCreateUser(), as to be able to associate a separate document in a different collection (holding user information) to a user when they are signed in.
//serverMain.js
Accounts.onCreateUser(function(options,user){
var userId = user._id;
user.profile = user.profile || {};
_.extend(user.profile, {profComp: false});
insertShopObject(userId);
return user;
});
The insert I am using is
insertShopObject(userId);
This inserts a new document with pre-set fields into a separate collection called ‘ShopList’, I have passed in the userId as a parameter which is added as a field into the ‘ShopList’ collection. I can see from the server console that the document _id is returned when I call insertShopObject(userId);
I somehow want to catch that id when the document is inserted and add it into the user.profile key on user creation like so
_.extend(user.profile,{shopId: <-- ?-->})
Here is the insertShopObject function, I have tried returning instead of console logging the ‘result’ into a holding variable with no luck.
//serverMain.js
insertShopObject = function(userId){
var newShop = {
//pre-set fields.....
}
ShopList.insert(newShop, function(error,result){
if(error){console.log(error);}
else {console.log(result)}
});
}

You need to make the insert synchronous for this to work. Omit the callback from ShopList.insert() and do:
insertShopObject = function(userId){
var newShop = {
//pre-set fields.....
}
var shopId = ShopList.insert(newShop);
return shopId;
}

Related

how to do angular update current user value of username in local storage

how to update local storage of a current User for only username when i update username its not reflecting in localstorage,am able to see the change in component page in console am getting null value for item and in console application localstorage null is stored key and value is {username:gasd} its not joining in that json. by using angular6
let item =localStorage.getItem(this.currentUser);
console.log(item);
let myobj = {username:changeValue};
localStorage.setItem(item, JSON.stringify(myobj));
Think of localStorage as a key-value dictionary.
You use string keys to get/set string values. (more on that in MDN docs)
So for objects you can do for example:
let myObj = {};
my["myKey"] = "myVal"; // note that in objects, values don't need to be strings
my["myKey2"] = 2;
my["myKey3"] = {};
In localStorage however it's strings on both sides:
localStorage.setItem("currentUser", {username: "ganes"}); // BAD
localStorage.setItem({username: "ganes"}, "someValue"); // BAD
localStorage.getItem({username: "ganes"}) // BAD
let currentUserDataStr = localStorage.getItem("currentUser"); // GOOD
// something along these lines
let currentUserData = JSON.parse(currentUserDataStr);
// do some mutation on currentUserData
currentUserData.currentUser = "ganesNew"
let newUserDataStr = JSON.stringify(currentUserData)
localStorage.setItem("currentUser", newUserDataStr); // GOOD

Generate non-identity primary key

My workplace doesn't use identity columns or GUIDs for primary keys. Instead, we retrieve "next IDs" from a table as needed, and increment the value for each insert.
Unfortunatly for me, LINQ-TO-SQL appears to be optimized around using identity columns. So I need to query and update the "NextId" table whenever I perform an insert. For simplicity, I do this during the creation of the new object:
var db = new DataContext( "...connection string..." );
var car = Car
{
Id = GetNextId<Car>( db ),
TopSpeed = 88.0
};
db.InsertOnSubmit( car );
db.SubmitChanges();
The GetNextId method is something like this:
public int GetNextId<T>( DataContext db )
{
using ( var transaction = new TransactionScope ( TransactionScopeOption.RequiresNew ) )
{
var nextId = (from n in db.GetTable<NextId> ()
where n.TableName == typeof(T).Name
select n).Single ();
nextId.Value += 1;
db.SubmitChanges ();
transaction.Complete ();
return nextId.Value - 1;
}
}
Since all operations between creation of the data context and the call to SubmitChanges are part of one transaction, do I need to create a separate data context for retrieving next IDs? Each time I need an ID, I need to query and update a table inside a transaction to prevent multiple apps from grabbing the same value. The call to SubmitChanges() in the GetNextId() method would submit all previous operations, which I don't want to do.
Is a separate data context the only way, or is there something better I could try?

Using Linq to update a List<T> of objects to DB

I have a form that returns me a List of FlatSessie objects
in my edit view I edit a few FlatSessie's and get them returned to my Post method in that List object.
In my DB I have Sessies, which I map using Automapper to FlatSessie's and back
now I can not get linq to make the update to the DB for me.
the code:
[HttpPost]
public ActionResult Sessies(int id, int? modID, int? projID, string schooljaarparam, List<FlatSessie> sl) {
if (ModelState.IsValid) {
foreach (FlatSessie s in sl) { //i run over all FlatSessies which i get
Models.Sessies ses = Mapper.Map<FlatSessie, Sessies>(s); // i map them to the Sessies object
List<Sessies> origReeks = _db.Sessies.Where(p => p.Ses_ID == ses.Ses_ID).ToList(); //i get the original Session by ID. if there is a Session with that ID, if not (the ID will be 0) i do an Insert. if there is i want to do an Update.
if (origReeks.Count > 0) {
//it's an update
UpdateModel(origReeks.First(); //doesnt work
//_db.Sessies.Attach(ses, origReeks.First()); //doesnt work, gives me an error on used ID...
_db.SubmitChanges();
} else {
//no sessies yet, add them, this works.
_db.Sessies.InsertOnSubmit(ses);
_db.SubmitChanges();
}
}
TempData["okmsg"] = "De sessies zijn opgeslagen";
return RedirectToAction("Index");
}
//if not valid, i return the viewdata which i need.
Module m = _db.Modules.First(md => md.Mod_ID == modID.Value);
int antses = m.Mod_AantalSessies.Value;
List<List<SelectListItem>> lpllst = new List<List<SelectListItem>>(antses);
for (int i = 0; i < antses; i++) {
lpllst.Add(MvcApplication.lesplaatsList(schooljaarparam, -1));
}
ViewData["lesplist"] = lpllst;
ViewData["lglist"] = MvcApplication.lesgeverList();
return View(sl);
}
It might work to provide a prefix to UpdateModel (FlatSessie[n], where n is such that it matches the actual input name of the model element in question) so that it knows which properties to map onto the object, but because you are getting a list of these it might not. Have you tried updating the retrieved model using the data from the matching FlatSessie object directly?
Also, once you get this to work, you might want to do a single SubmitChanges for all inserts/updates (outside the loop) so that you get the entire submit wrapped in a single transaction. This will make it easier if there are errors to correct them and resubmit -- since you won't have some changes already committed causing further potential errors.

LINQ variable to list of string without using column names?

In an C# ASP.Net MVC project, I'm trying to make a List<string> from a LINQ variable.
Now this might be a pretty basic thing, but I just cannot get that to work without using the actual column names for the data in that variable. The thing is that in the interests of trying to make the program as dynamic as possible, I'm leaving it up to a stored procedure to get the data out. There can be any amount of any which way named columns depending on where the data is fetched from. All I care about is taking all of their values into a List<string>, so that I can compare user-input values with them in program.
Pointing to the columns by their names in the code means I'd have to make dozens of overloaded methods that all just basically do the same thing. Below is false non-functioning code. But it should open up the idea of what I mean.
// call for stored procedure
var courses = db.spFetchCourseInformation().ToList();
// if the data fails a check on a single row, it will not pass the check
bool passed = true;
foreach (var i in courses)
{
// each row should be cast into a list of string, which can then be validated
// on a row-by-row basis
List courseRow = new List();
courseRow = courses[i]; // yes, obviously this is wrong syntax
int matches = 0;
foreach (string k in courseRow)
{
if (validator.checkMatch(courseRow[k].ToString()))
{
matches++;
}
}
if (matches == 0)
{
passed = false;
break;
}
}
Now below is an example of how I currently have to do it because I need to use the names for the columns
for (int i = 0; i < courses.Count; i++)
{
int matches = 0;
if (validator.checkMatch(courses[i].Name))
matches++;
if (validator.checkMatch(courses[i].RandomOtherColumn))
matches++;
if (validator.checkMatch(courses[i].RandomThirdColumn))
matches++;
if (validator.checkMatch(courses[i].RandomFourthColumn))
matches++;
/* etc...
* etc...
* you get the point
* and one of these for each and every possible variation from the stored procedure, NOT good practice
* */
Thanks for help!
I'm not 100% sure what problem you are trying to solve (matching user data to a particular record in the DB?), but I'm pretty sure you're going about this in slightly the wrong fashion by putting the data in a List. I
t should be possible to get your user input in an IDictionary with the key being used for the column name, and the object as the input data field.
Then when you get the data from the SP, you can get the data back in a DataReader (a la http://msmvps.com/blogs/deborahk/archive/2009/07/09/dal-access-a-datareader-using-a-stored-procedure.aspx).
DataReaders are indexed on column name, so if you run through the keys in the input data IDictionary, you can check the DataReader to see if it has matching data.
using (SqlDataReader reader = Dac.ExecuteDataReader("CustomerRetrieveAll", null))
{
while (reader.Read())
{
foreach(var key in userInputDictionary.AllKeys)
{
var data = reader[key];
if (data != userInputDictionary[key]) continue;
}
}
}
Still not sure about the problem you are solving but, I hope this helps!
A little creative reflection should do the trick.
var courses = db.spFetchCourseInformation()
var values = courses.SelectMany(c => c.GetType().GetProperties() // gets the properties for your object
.Select(property => property.GetValue(c, null))); // gets the value of each property
List<string> stringValues = new List<string>(
values.Select(v => v == null ? string.Empty : v.ToString()) // some of those values will likely be null
.Distinct()); // remove duplicates

How can i get primary key value when i insert a new record?

I am using LINQ-to-SQL class. It has a method object.InsertOnSubmit() .But it returns void so can i get primary key values after inserting a record.
I want the primary key value of recently inserted record.
yes (Assuming it is an identity field).
Calling InsertOnSubmit alone doesn't send the insert to the db. You need to call SubmitChanges in order for any changes in the current datacontext instance to be sent to the db.
After you have called SubmitChanges, you can access the values from the instance you used when calling InsertOnSubmit. Linq to sql will populate those values for you when doing the insert (which occurs during SubmitChanges)
Check this example: http://msdn.microsoft.com/en-us/vbasic/bb737920.aspx#dynid
In short, you don't need to. The object itself is updated.
public void Add(Person person)
{
using (MyEntities context = new MyEntities())
{
Context.Persons.InsertOnSaveChanges(person);
Context.SaveChanges();
}
}
public void Foo()
{
Person p = new Person { name = "John", age = 20 }
Add(p);
Int32 id = p.id; // id contains the newly inserted object's id
}
Here's an example of how that works:
var dc = new MyDataContext();
var cust = new Customer{FirstName="John", LastName="Smith"};
dc.Customer.InsertOnSubmit(cust);
dc.SubmitChanges();
//after SubmitChanges(), the Id is filled from the database
var customerPrimaryKey = cust.Id;
If the model is set up properly, the PK should be set on the affected object (the one you just inserted) automagically.
HTH.
Seth
Once you have called the InserOnSubmit(),primary key value is set to the corrosponding fiels in youe table object. You can simply access that property to get Primary Key.
Are you calling SubmitChanges() on your data context after inserting the record? The changeset won't be evaluated until you do.