How to update security stamp of users in bulk? Asp.net Identity - asp.net

I am updating users security stamp when a user is being deactivated. I can do this for one user like this.
await UserManager.UpdateSecurityStampAsync(userId);
I want to do this form multiple users, like 500 or may bee 100.
Is there any way I can do this in bulk?
I am using entity framework.

Security Stamp is a random string with no significant importance of the actual value, so you can just stuff new GUID there.
Best way to do it in bulk would be to execute SQL query:
update ApplicationUsers set SecurityStamp = NEWID()
You can specify where clause as needed to limit users you need to update, and most likely you'll need to change the name of the table to what you actually have in your DB.
There different ways to execute this query - you can do this with EF:
context.Database.ExecuteSqlCommand("UPDATE ApplicationUsers........");
Or you can look into already recommended EF.Extended library - bulk update is possible without dipping into SQL.

You can use Entity Framework Extended Library.Which is the fastest way to do the update.Extended Library batch update eliminates the need to retrieve and load an entity before modifying it.So it is very fast.Try that.
Example from their doc :
//update all tasks with status of 1 to status of 2
context.Tasks
.Where(t => t.StatusId == 1)
.Update(t => new Task { StatusId = 2 });
You can read more about it here : Entity Framework Extended Library

Related

Asp.net Multi Tenancy implementation on existing solution

I have an asp.net MVC solution, Entity Framework code first, which has dozens of database tables all designed around a single company using the solution.
The requirement has come up to allow multiple companies to use the solution, so what we have done is add "CompanyID" as a column to all database tables and set a default value. There is a company table with the various company names and CompanyID's. On login the user selects the company they are logging in as which stores the CompanyID in the session.
At the moment every Entity Framework call now has to be updated to include the CompanyID, for example when selecting Employees I am doing:
List<Employee> employees = db.Employees.Where(x => x.CompanyID = Session.CompanyID).ToList();
As you can see it will be tedious to do this on thousands of calls to the db. Any update, save, and fetch has to change.
Surely I am doing it the long way and there is a way at runtime, globally to append all DB calls to include the CompanyID stored in the logged in users Session? Something that dynamically appends the CompanyID when fetching values or storing etc? Perhaps a package I can use to do this task at runtime?
In my opinion, there is no need to add CompanyID to EVERY table in the database. I would select just "root" tables/entities for that. For example, Employee or Department clearly sounds like a many-to-one relationship with a company - so adding CompanyID there sounds right. But, for example, EmployeeEquipment which is a many-to-one relationship with Employee does not have to have CompanyID column since it can be filtered by the joined Employee table.
Regarding your request to filter by CompanyID globally, I'm not aware of anything that can do that per request. There are global filters for Entity Framework, but I'm not sure how you can apply them per-request. Take a look on .HasQueryFilter() during model creation if you are using Entity Framework Core.

How can you create a transaction/batch write between multiple Firestore instances?

Firebase allows having multiple projects in a single application.
// Initialize another app with a different config
var secondary = firebase.initializeApp(secondaryAppConfig, "secondary");
// Retrieve the database.
var secondaryDatabase = secondary.database();
Example:
Project 1 has my users collection; Project 2 has my friends collection (suppose there's a reason for that). When I add a new friend in the Project 2 database, I want to increment the friendsCount in the user document in Project 1. For this reason, I want to create a transaction/batch write to insure consistency in the data.
How can I achieve this? Can I create a transaction or a batch write between different Firestore instances?
No, you cannot use the database transaction feature across multiple databases.
If absolutely required, I'd probably instead create a custom locking feature. From wiki,
To allow several users to edit a database table at the same time and also prevent inconsistencies created by unrestricted access, a single record can be locked when retrieved for editing or updating. Anyone attempting to retrieve the same record for editing is denied write access because of the lock (although, depending on the implementation, they may be able to view the record without editing it). Once the record is saved or edits are canceled, the lock is released. Records can never be saved so as to overwrite other changes, preserving data integrity.
In database management theory, locking is used to implement isolation among multiple database users. This is the "I" in the acronym ACID.
Source: https://en.wikipedia.org/wiki/Record_locking
It's been three years since the question, I know, but since I needed the same thing I found a working solution to perform the double (or even ^n) transaction. You have to nest the transactions like this.
db1.runTransaction(t1 => db2.runTransaction(t2 => async () => {
await t1.set(.....
await t2.update(.....
etc....
})).then(...).catch(...)
Since the error is propagated in the nested promises it is safe to execute the double transaction in this way because for a failure in any one of the databases it results in the error in all of them.

AddOrUpdate() throws error: Modifying a column with the 'Identity' pattern - how should I be handling this?

I've been working through Adrian Hall's book on integrating Xamarin and Azure Mobile Apps. In Chapter 3 he adds a User table to facilitate "Friends" data. In his implementation, the client authenticates the user and then makes a request to a custom endpoint that either adds the user to the database or updates their record. Here's an abridged version of the method in the custom controller:
[HttpGet]
public async Task<IHttpActionResult> Get()
{
// ...Obtain user info
User user = new User()
{
Id = sid,
Name = name,
EmailAddress = email
};
dbContext.Users.AddOrUpdate(user);
dbContext.SaveChanges();
// ...
}
The trouble is, the 2nd time the same user logs in to the app, this code throws an exception saying
Modifying a column with the 'Identity' pattern is not supported. Column: 'CreatedAt'. Table: 'CodeFirstDatabaseSchema.User'.
This StackOverflow Answer explains that this is because the AddOrUpdate() method nulls out any properties not set on the entity, including CreatedAt, which is an identity column. This leaves me with a couple of questions:
What is the right way to Add or Update an entity if the CreatedAt value cannot be edited? The same SO thread suggests a helper method to look up the existing CreatedAt and apply it to the entity before trying to save it. This seems cumbersome.
Why is this implemented as a custom auth controller that returns a new Auth token when it only needs to add or update a User in a database? Why not use a normal entity controller to add/update the new user and allow the client to continue using the Auth token it already has?
For the CustomAuthController.cs code, see here.
When you focus on what you are trying to do from SQL perspective it would be like:
update dbo.some_table set some_primary_key = new_primary_key where some_primary_key = ...
which would result in cannot update identity column some_primary_key which makes sense.
But if you do have a reason to update the PK you still can do it if you set the identity insert
SET IDENTITY_INSERT dbo.some_table ON;
Then after you made an insert you set it off using similar syntax.
But this is rather exceptional scenario.
Usually there is no need to manually insert PKs.
Now going back to EF.
The error you are getting is telling you that you cannot modify a column with PK, most likely user_id and/or some other columns if you have composite PK.
So, first time round a new user gets created. Second time round, because you are suing GetOrUpdate a user gets udpated but because you are passing PK it breaks.
Solution?
AddOrUpdate was meant to help with seeding the migrations only.
Given its destructive nature I would not recommend using GetOrUpdate anywhere near production.
You can replace GetOrUpdate with two operations Get and Update
Fetch user and then
if not exists then create a new one
or if it does exist then update it

How to entirely skip validation in simple schema and allow incomplete documents to be stored?

I'm creating an order form and a schema defined for an Order (certain required fields such as address, customer info, items selected and their quantities, etc).
a. User visits site.
b. A unique ID is generated for their session as well as a timestamp.
var userSession = {
_id: createId(),
timestamp: new Date(),
};
var sessionId = userSession._id;
c. The userSession is placed in local storage.
storeInLocalStorage('blahblah', sessionObject);
d. An Order object is created with the sessionId as the only field so far.
var newOrder = {
sessionId: sessionId;
};
e. Obviously at this point the Order object won't validate according to the schema so I can't store it in Mongo. BUT I still want to store it in Mongo so I can later retrieve incomplete orders, or orders in progress, using the sessionID generated on the user's initial visit.
This won't work because it fails validation:
Orders.insert(newOrder);
f. When a user revisits the site I want to be able to get the incomplete order from Mongo and resume:
var sessionId = getLocalStorage('blahblah')._id;
var incompleteOrder = Orders.findOne({'sessionId', sessionId});
So I'm not sure how to go about doing this while accomplishing these points.
I want full simpleschema validation on the Orders collection when the user is entering in items on the forms and when the user is intending to submit a full, complete order.
I want to disable simpleschema validation on the Orders collection and still allow storing into the DB so that partial orders can be stored for resumption at a later time.
I can make a field conditionally required using this here but that would mean 50+ fields would be conditionally required just for this scenario and that seems super cumbersome.
It sounds like you want to have your cake, and eat it too!
I think the best approach here would be keep your schema and validation on the Orders collection, but store incomplete orders elsewhere.
You could store them in another collection (with a more relaxed schema) if you want them on the server (possibly for enabling resume on another device for the logged in user) , or more simply in Local Storage, and still enable the resume previous order behaviour you are wanting.
Only write to the Orders collection when the order is complete (and passes validation).
Here's a variation on #JeremyK's answer: add an inProgress key to your order of type [Object]. This object would have no deeper validation. Keep your in progress order data in there until the order is final then copy/move all the relevant data into the permanent keys and remove the inProgress key. This would require that you make all the real keys optional of course. The advantage is that the object would maintain its primary key throughout the life cycle.
I think this particular case has been solved; but just in case, you can skip Simple Schemma validations by accessing MongoDB native API via Collection#rawCollection():
Orders.rawCollection().insert(newOrder);
While this question is very old in the meantime there is a better solution. You probably use simple schema together with collection2. Collection2 has the ability to set multiple schemas based on a selector and then validate against the correct schema based on it.
https://github.com/Meteor-Community-Packages/meteor-collection2#attaching-multiple-schemas-to-the-same-collection
e.g. you could have a selector {state: 'finished'} and only apply the full schema to these documents while having another selctor, e.g. {state: 'in-progress'} for unfinished orders with a schema with optional fields.

Best way to check a setting in all profiles

Using ASP.net, is there a recommended best way to access a particular field of the profile in code. I was looking in my old Problem-Design-Solution 2.0 book, and it does it by pulling all members in the DB and then iterating through each one's profile (see code below). Is there a better way?
for each (MembershipUser user in Membership.GetAllUsers())
{
ProfileCommon userProfile = profile.GetProfile(user.UserName);
if (userProfile.mysetting == desiredValue)
{
//do something
}
}
Edit 1
I found that it can be done a little more efficiently than pulling members and then pulling profiles. It is possible that not all members have a profile, so if you use the following code, you'll pull all the profiles (which may be fewer in number than members, and then can iterate across it:
for each (ProfileInfo theProfile in ProfileManager.GetAllProfiles (ProfileAuthenticationOption.All)
{
ProfileCommon pc = ProfileBase.Create(theProfile.UserName)
if (pc.mysetting == desiredValue)
{
//do something
}
}
It still round trips the DB for each profile, but it may not do it as many as if we used the members...
With built-in Profiles, no there isn't a better way. One option as provided by Tim is Table Profile provider or writing your own profile provider.
Or you can go completely other route i.e. storing profile information in your own custom table.
You could use the Table Profile Provider and build custom queries to get your desired settings.
You could probably do better with linq, I don't have VS with me right now, but pseudo code would look something like this:
var users = from MembershipUser user in Membership.GetAllUsers()
where user.mysetting == desiredValue
select user
then iterate over the users,
foreach(MembershipUser u in users) {
// do something
}
that should only contain the ones of interest. Linq should handle executing the SQL for you correctly, but you can check to see what it's doing with profiler.
EDIT
Actually that probably won't get you anything from a performance perspective, the GetAllUsers is going to bring back everything. You might want to create a linq2sql dbml map for the users table and use that instead of Membership class for querying against a custom property.
EDIT 2
ASP.NET Roles and Profiles: best way to query for collection of users who match custom profile property?
If you're using the table profile provider you may be able to use the linq query against that table:
http://weblogs.asp.net/kencox/archive/2010/09/05/using-the-sql-table-profile-provider-in-asp-net-4-web-applications-c-amp-vb.aspx

Resources