DotNetOpenAuth - Database.DataContext.AddToUser(user) does not work - c#

I am incorporating DotNetOpenAuth to my asp.net website. I am new with Entity framework.
Database.DataContext.AddToUser(user) located in LogingFrame.aspx.cs does not add a user into the database. User and AuthenticationToken records are filled correctly. The same code from template project, which points to the same database, works fine. Probably I missed something during incorporation. Could you
please point what I have to check? Please let me know if you need any code to be provided.

...does not add a user into the database. User and AuthenticationToken records are filled correctly.
Your question seems to contradict itself, or I'm reading it wrong. It sounds like you're saying no user is added, but then a user is added.
Let me take a stab at it though and let you know how this project template works. A database transaction wraps all database changes within a single HTTP request. It's built into the RelyingPartyLogic assembly to have this behavior. Also, at the end of a successful HTTP request (one that didn't result in an unhandled exception) SaveChanges() is called and the transaction is committed. If an unhandled exception is thrown, the changes and transaction are rolled back. This helps to protect the integrity of your database.
A side-effect of this is, however, that if you're debugging through an "add a user" method and after you see AddToUser executed you jump to the users table to see if it was added, it won't be there because SaveChanges hasn't yet been called and the transaction hasn't been committed yet.
Per standard Entity Framework behavior, SaveChanges must be called for your changes to be persisted in the database, but as I said before, the RelyingPartyLogic library makes this call for you. But you may sometimes need to call SaveChanges yourself in your own code in order to (for example) get the ID of a newly added row. This works even within a transaction before committing it.
Hope that helps.

Did you forget to call DataContext.SaveChanges()?

Related

Multi-threading problems on Entity Framework Core

I'm using Entity Framework as my way of communicating with the database and fetching/writing information on it, on a ASP.NET CORE application. (Used as a very basic API, acting as a server for a separate application.)
There comes a time when the clients make requests to join a given lobby. I've just confirmed that if 4 requests at the same time enter, they will all be signed up on the lobby, but the player count did not update, and if it did - it'd go over the top/limit.
Am I using entity framework wrong? Is there an alternative tool to be used for such things, or should I just make it so it uses a single thread (If someone can remind me how), or encapsulate all my actions/endpoints with a lock block statement?
No matter how I structure my code, it's all prone to these same-timed http requests, moving parallelly through my repository/context.
It'd be great if I could make some kind of a queue, which I believe is what encapsulating everything in a lock would do.
EDIT:
As answered by vasily.sib, I can resolve this with the use of concurrency tokens. Please check his comment for some amazing information on how to use them!
Your problem is that operations like these...
_context.Sessions.FirstOrDefault(s => s.Id == sessionId).PlayerCount += 1;
_context.SaveChanges();
...are not atomic. With FirstOrDefault you get the session (which you dereference then without a null check, so First would be a better option here, since you will get a better error message). Then you save the changes in another step. Between those steps another concurrent thread could have changed and already saved a new value for PlayerCount.
There are multiple ways to resolve this, and most of them would require some changes on DB level.
One way to resolve it is to write a stored procedure that can do the update atomically. You would need an UPDATE statement similar to this one:
UPDATE Sessions
SET PlayerCount = PlayerCount + 1
FROM Sessions
WHERE Id = #SessionId
If you don't want to use stored procedures you could send this SQL directly to the DB.
One problem with this solution is that later you also do this step:
if (thisSession.Size == thisSession.PlayerCount)
{
thisSession.Status = SessionStatus.Active;
_context.SaveChanges(); // this can be trimmed and added at the previous scope
}
You would have to integrate this in your UPDATE statement to keep the operation atomic. If you want to add additional steps, things can get complicated.
Another way is to use optimistic concurrency built into EF core. In a nutshell, this means that when you save the data ef will first check whether the destination row is still in the same version compared to the moment you retrieved it.
To achieve that, your session needs a column that will contain a version counter. For SQL Server this would be a colun of type rowversion. Once you have this column, EF can do its optimistic concurrency magic. EF will throw a DbUpdateConcurrencyException which you would have to handle. There are different ways to resolve the error. One easy way would be to repeat your entire operation until it works out.

How to save changes to disk with Entity Framework when connection goes down so next time app starts it propagates the changes

Is it possible to keep on to the 'changes' you will be wanting to make with Entity Framework?
For instance I do an update query then the connection fails, I close the app and then tomorrow I want it to do that update query when a connection is restored.
Is a thing like that possible with Entity Framework 6?
You could possibly create your own ChangeTracker, like in this tutorial, which saves all changes to a file. Parsing the file for a later use might be tricky.
The other option would be to use retry logic and hope the connection problem was just a slight hiccup
I think ZorgoZ is right and this answer will not address your actual question, but what I think it is your actual problem (see XY problem): you fail to save some changes (business-wise) and you want to be able to retry saving them later, not necessary some EF changes that you want to persist a later moment.
One way to do it is to store the business information that trigger the change and retry the whole flow:
define some sort of queue stored in a file, isolated storage etc. (depends on your technology)
your update flow should persist some sort of record / object in the queue that contains all relevant information + a status (e.g. Queued, Save error etc.)
update is tried. If it fails, you can have a status update (e.g. Save error)
the user closes the application
later, the user opens the application seeing the queue items status (item 1 saved OK, item 2 save error etc.)
Besides EF technical issues, this implementation allows for flow changes that include things outside EF save changes (e.g. also check some external API) and abstracts away the data access layer entirely (EF changes serialisation implementation has a big chance to depend on some EF specifics).
Also I sense context information serialization (e.g. data behind some form) is easier to implement than EF context changes serialization.

What is the purpose of auto-creating tables in SimpleMembershipInitializer if I am using my own database for security?

I am trying to use SimpleMembership with my own database that already has all the users/roles/etc...
To that end, I change the WebSecurity.InitializeDatabaseConnection line in the SimpleMembershipInitializer constructor to point to my own table (note autoCreateTables: true):
WebSecurity.InitializeDatabaseConnection("NameOfMyConnectionString", "User",
"UserId", "DomainLogin", autoCreateTables: true);
I then created my own provider where I overrode the 'ValidateUser' method.
At this point, I fired up the app, logged in and then logged out (that is all that's required for my app - account creation is elsewhere). I looked at my database and the following tables were created: webpages_Membership, webpages_OAuthMembership, webpages_Roles, webpages_UsersInRoles. However, there was nothing in the tables. I fired up the Profiler, repeated the operation and in no way were those tables ever being referenced.
So am I safe changing the autoCreateTables parameter from true to false?
P.S. Yes, I read this question, but it did not answer my specific question.
Basically, the MVC team wanted to give folks the ability to get up and running quickly without having to do a lot of the mundane user\role provisioning that comes with a brand new project - the concept being, get a database, create some kind of users table, and let the SimpleMembershipProvider take care of the rest (it's just so simple!).
Since you've already started down the path of creating your own custom provider, there is no reason to have those extra tables, so you're absolutely safe to set autoCreateTables to false.

How to prevent rollback of entire ChangeSet when PersistChangeSet fails in Silverlight/RIA

In my scenario, I typically put all my database persistence logic in a PersistChangeSet override, since it makes it easier for me to synchronize my save stored procedure wrapper calls involving entities that reference ids in other entities (for example, in case I have an entity A that references a temporary id of -1 in another entity B, I want to be able save entity B first, then update its id reference in entity A with the id returned from the database for entity B).
When one stored procedure returns an error for whatever reason, I just throw a custom exception with the message returned by the stored procedure and leverage the SubmitOperation object's HasError and Error properties on the client side (view model) in order to inform the user what went wrong.
The problem I'm having with the approach just described is that persistence errors rolls back the entire ChangeSet, even if , say, 2 out of 3 "persistence operations" (i.e. calls to stored procedure wrappers) succeed. So, for instance, if I had set a temporary id of -1 for an entity on the client side and then in PersistChangeSet I updated that id to a new value after a successful save to the database, by the time I get back to the SubmitChanges callback that id will have reverted to -1 (because some other entitity failed to save in PersistChangeSet). Ideally, entities that were persisted successfully should be removed from the ChangeSet by the time SubmitChanges completed.
I hope I have described my issue sufficiently well, but feel free to ask for any clarifications. I'm open to suggestions in case the approach I described above is not ideal or otherwise violates the governing principles of RIA.
Thanks in advance for your help!
I resolved this issue by using a TransactionScope in an override of the Submit method in my domain service. This allows the PersistChangeSet to behave as a unit of work (in other words, changes are only persisted if all operations are successful).
Details here: http://msdn.microsoft.com/en-us/library/ee707364(v=vs.91).aspx

In EF, call SaveChanges from SavingChanges event?

I'm using EF 4.1 in an MVC 3 application.
My goal is to save all changes in another database for logging purposes.
I have implemented the SavingChanges event for an EntityContext. In that event, I'm extracting changes via the GetObjectStateEntries() , that works fine.
Then, I have another EntityContext, that works against a different model and database, for the logging. I create that Context, create logging Entities, adding them to the logging Context. All seems to work fine. Then when I call SaveChanges() on the logging context, Exception occurs, that says that I cant insert because the Id is null (which I know for sure that it isn't).
Does anyone know if it's impossible to achieve this? Am I missing some important detail?
The case was that I had used "Model first" in my logging model, and "DB first" in all other models. That resulted in the mistake that the EF configuration was expecting take care of the Id (GUID) itself, but I was trying to supply one myself. I deleted the entities from the model, and instead, imported them from the DB, and that solved the problem!
Thanks to #Eranga for setting me in the right direction.

Categories

Resources