ASP.NET Entity Framework trying to update single column - c#

I am using ASP.NET Entity Framework and I am trying to update a single column with the following code:
[HttpGet]
public void MarkOffline(string online)
{
Users user = new Users { email = online, isOnline = false };
db.Entry(user).Property("isOnline").IsModified = true;
db.SaveChanges();
}
But I get this error:
Member 'IsModified' cannot be called for property 'isOnline' because
the entity of type 'Users' does not exist in the context. To add an
entity to the context call the Add or Attach method of DbSet<Users>.
The part I don't know how to do:
To add an entity to the context call the Add or Attach method of
DbSet<Users>.
How do I fix my problem?

If you want to update like this, you'll need to Attach the entity where the entity has its primary key set.
Given you don't have its primary key but only one of its (unique, hopefully) fields, you need to query the record first and then update it:
var existing = db.Users.FirstOrDefault(u => u.email == email);
existing.IsOnline = true;
db.SaveChanges();
That being said, this is not how you record a user's online status in a web application. You rather update a user's LastAction timestamp with each action they perform, and mark a user as offline at runtime when their LastAction is more than N seconds or minutes ago.

Related

Entity Framework Core not returning data

I have a new .NET Core application that is using Entity Framework Core. The query against the database returns no data.
The context is created like this:
private readonly ExtensionDataModel.DataSet1 _context = new ExtensionDataModel.DataSet1();
and the method using it is:
public ExtensionDetails GetExtensionDetails(string extension)
{
var users = _context.Users;//.Where(x=>x.activeFlag==true);//.Where(x => x.workPhone.Contains("7029"));
if (!users.Any())
{
return null;
}
var user = users.First();
var detail = new ExtensionDetails()
{
Extension = user.workPhone,
FirstName = user.firstName,
LastName = user.lastName,
Location = user.LocationsRow.LocationDesc
};
return detail;
}
I get no errors, and the users.Any returns false, even through there is data in the database. If I expand the users object in the debugger, and look at the result set, the result set is empty. Also, I have been unable to see the query that it is generating.
When I use SQL Server Profiler, it does not show any database activity.
When I go to the Entity Framework designer (clicking on DataSet1.xsd), I can right click on the users table and choose Preview Data, and it brings back the rows in the table.
I am using a separate SQL Server database server, and created the EF model by extracting it from the database.
My data model has two tables in it, and the user that I am using has only read access to those two tables.
Any help would be appreciated. I am new to .net core, but have been using EF for many years.

Attempting to create ASP.Net Core Identity data in an existing table with existing user records

I have a new ASP.Net Core website that uses an existing database, to which
I have added ASP.Net Core Identity for user management.
Since there is an existing user table, I simply added the which I have properly added the ASP.Net identity columns.
The additional columns in the existing table are in my IdentityUser-derived class. The site logic works well when I create new users, as well as logging in, logging out, and the like.
The problem is that all of the existing 'user' records (which I will call MyUser) have blank Core Identity fields, and thus are invisible to the identity system calls.
I would like to write a utility that goes through the existing MyUser records, and if the AspIdentityId field is null, set it up as a record manageable by the Identity subsystem.
I'm essentially looking for the 'Create' call, but I can't use UserManager.
CreateAsync because this creates a new record in the table, it doesn't update an existing one.
I do have two DB contexts (IdentityDBContext and OriginalDBContext), so if there is something that allows me to generate the field data, I can then add this to the columns in the table for the associated record.
Ok, I got this to work, not entirely sure why it works, seems like the AspIdentity fields are populated before they are committed. I have only added the specific changes that were the crux of the question, the DI, setup of the contexts, etc are elsewhere in the project.
Essentially, for each 'domain' record, I create a new ApplicationUser (IdentityUser-derived) record, and add the values for the custom fields in the domain record into the ApplicationUser record. Once this object is created, it has the necessary Asp.Net Identity fields already populated. I then get those fields and populate them back onto the domain specific record, then I save this. Once that is done, I re-find the record (this may not be necessary), and add the password based on the plain text password already in the domain record.
var clients = new List<Client>(myService.myContext.Clients);
foreach (var client in clients)
{
var user = new ApplicationUser // Derived from IdentityUser
{
UserID = client.UserID,
FirstName = client.FirstName,
LastName = client.LastName,
UserName = client.UserName,
PhoneNumber = client.Phone,
Email = client.Email // Other fields omitted for brevity.
};
var idUser = user as IdentityUser;
client.AspIdentityId = user.Id;
client.ConcurrencyStamp = user.ConcurrencyStamp;
client.NormalizedEmail = user.NormalizedEmail;
client.NormalizedUserName = user.NormalizedUserName;
client.PasswordHash = user.PasswordHash;
client.SecurityStamp = user.SecurityStamp;
myService.myContext.SaveChanges();
// Can we just use the 'user' object here?
var newUser = await myService.UserManager.FindByIdAsync(client.AspIdentityId);
var result = await myService.UserManager.AddPasswordAsync(newUser, client.Password);
}
Hope this helps someone, this was important to me to get done this way.

Dynamics CRM custom workflow before entity deletion

I'm trying to make a custom workflow on Dynamics CRM. I need to delete some entities when another entity is deleted.
I created my class library and I retrieved the Guid of the deleted entity with this code:
protected override void Execute(CodeActivityContext executionContext)
{
ITracingService tracingService = executionContext.GetExtension<ITracingService>();
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory =
executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service =
serviceFactory.CreateOrganizationService(context.UserId);
mService = service;
mExecutionContext = executionContext;
Guid myTipologyTypeDeleted = context.PrimaryEntityId;
bool isReading = context.PrimaryEntityName.Equals(new_tipologialettura_richiesta.EntityLogicalName);
bool isMaintenance = context.PrimaryEntityName.Equals(new_tipologiamanutenzionerichiesta.EntityLogicalName);
bool myResult = AddOnIntervention(isReading, isMaintenance, myTipologyTypeDeleted);
// Retrieve the summands and perform addition
result.Set(executionContext, myResult);
}
And here all works, I get the Guid and I get the type (reading or maintenance).
My problem is when I try to retrieve the entity with this code (the same code is working perfectly in another workflow started on record creation, but on record delete gives me error).
Entity myReadingEntity = mService.Retrieve(new_tipologialettura_richiesta.EntityLogicalName, myTipologyTypeDeleted, new ColumnSet(true));
Here I get an exception saying that no record of type MyType with id myId has been found.
I checked the record and it still exist in the DB so it has not been deleted. What I'm doing wrong?
Thanks
I think the best thing to write your custom logic here will be a Plugin, You Should write a plugin that runs on the
Message: Delete
Stage: POST
After registering the plugin on Post Delete Operation, you should add an pre-image that will be available on Post Delete with all the attributes.Instead of issuing a retrieve, the best practice is to push the required data in an image instead.
Taken from MSDN:
Registering for pre or post images to access entity attribute values results in improved plug-in performance as compared to obtaining entity attributes in plug-in code through RetrieveRequest or RetrieveMultipleRequest requests.
In your plugin change the lines of code:
Entity myReadingEntity = mService.Retrieve(new_tipologialettura_richiesta.EntityLogicalName, myTipologyTypeDeleted, new ColumnSet(true));
to
if (context.PreEntityImages.Contains("YourImageName"))
{
Entity myReadingEntity = context.PreEntityImages["YourImageName"]
}

Unexpected Behaviour while trying to update database in consecutive requests - EF 6

I have been dealing with this for days
Summary
I am creating a Social site that will be the back bone for another web application. The hangup is when I submit a request to create a group all goes well, but if I attempt to submit this form again with different data I get a DbEntityValidationException. The exception is related to the ApplicationUser entry.
Details
When I start the Application in Debug mode and submit the Group creation form for the first time it will succeed, adding all the entities into the database as excepted. I have verified this and all looks good. While in the same Debug session, I change the information in the form, to create another group, and submit the form, which leads to the DbEntityValidationException.
The error is related the when I try to insert a SocialGroupMemberModel which contains a reference to the User, and other details related to the users status in the group. The User entry is being marked as added and EntityFramework is trying to insert the User instead of updating. I have attempted to set the Navigation (User) and set the ForeignKey (UserId), both lead to the same error.
I am using HttpContext.Current.GetOwinContext().Get<ApplicationDbContext>();
In the Controller I use ApplicationUserManager to get the User Entity, I then pass this to the Repository to create the group (in either case, either passing the ID, or Entity itself, doesn't work the second time)
Group Creation Code:
var groupInfo = new SocialGroupInfo
{
Created = DateTime.Now,
Description = model.Description,
ShortDescription = model.ShortDescription,
Name = model.Name,
Tags = TagRepo.GetTags(),
Members = new List<SocialGroupMember>()// { member }
};
var groupModel = new SocialGroupModel
{
Slug = model.Slug,
Info = groupInfo
};
Context.SocialGroups.Add(groupModel);
var member = new SocialGroupOwnerModel
{
Joined = DateTime.Now,
UserId = creator
//User = null
//Group = groupInfo
};
groupInfo.Members.Add(member);
//creator.SocialGroups.Add(member);
SaveChanges();
The Validation Error is: "User name ** is already taken" so this leads me to believe that on the second attempt to add the new group, it is attempting to add a new user.
Please ask for any additional information needed, thanks.
This issue was caused by the IoC holding a reference to the previous DbContext, unsure as to why, but removing all usage of Autofac fixed the issue.
Very anticlimactic solution, but issue fixed...
Now the issue is to figure out why Autofac was behaving this way, all Debugging showed that the classes were created each request... but that is another question.

Get Identity value from DataBase on Object creation

I' running a ASP.Net MVC 3 application on Azure. I simply create some users with name and add them in the SQLAzure DB.
Is it possible to get the id of the user on creation or do I need to make a request to the DB.
I actually have:
User user = new User(name);
db.Users.Add(user);
db.SaveChanges();
//Here get the user db generated id
Thanks a lot.
Not sure if it is the same in Azure but when using the entity framework all you have to do to access the ID is user.UserID (or whatever the name of the property is from your db) right after the SaveChanges() call.

Categories

Resources