I am having a problem in editing the role of a user. I have these codes:
`
Entities db2 = new Entities();
private UsersContext db = new UsersContext();
//
// POST: /AdminOnly/Edit/5
[Authorize(Roles = "Owner")]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(UserProfile userprofile, int? roless)
{
if (ModelState.IsValid)
{
webpages_UsersInRoles s = new webpages_UsersInRoles();
s = db2.webpages_UsersInRoles.Where(m => m.UserId == userprofile.UserId).FirstOrDefault();
if (s != null) //with existing role, edit it
{
s.RoleId = roless.Value;
db.Entry(userprofile).State = EntityState.Modified;
db2.Entry(s).State = EntityState.Modified;
db.SaveChanges();
db2.SaveChanges();
return RedirectToAction("Index");
}
else //no existing role
{
//some code here
}
}
ViewBag.roless = new SelectList(db2.webpages_Roles, "RoleId", "RoleName");
return View(userprofile);
}
`
When I try to save the changes in the database, db2.SaveChanges(); throws me an error that says:
An exception of type 'System.InvalidOperationException' occurred in
System.Data.Entity.dll but was not handled in user code
Additional information: The property 'RoleId' is part of the object's
key information and cannot be modified.
What should I do? Thanks in advance!
RoleId is used as key constraint and main identifier of entity. You can't change this id. Just don't update this property or add more comments why do you need to update it.
It's saying that RoleId is part of the primary key and cannot be changed. Instead of editing the existing row in webpages_UsersInRoles, try deleting that row and adding a new one with the new RoleId value.
Turns out that the column I want to change is a compound foreign key. I need to remove the first value of the RoleId and save the changes to the table. And add again the second value and save the new changes to the table. Thanks to those who helped!
Related
I am very new to c# and asp.net mvc. I'm building a HR portal for our company where a user can submit a leave form among other things... So I'm using mssql as the database server and using Entity Frame work to communicate with it. I have 3 entities, user (Containing user details), permissions (the user permissions for allowing actions in the app) and then the leave form table (where the leave form details are stored). There is a one to many relationship between user - permission and then a one to many relationship between user-leave. I am not fazed about the permissions as that gets created when the user account is being created.
The problem I am facing is, how do I add a leave form for a specific user? Below is my controller code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Leave(MasterViewModel model)
{
DocSubViewModel mv = model.DSModel;
int userId = Convert.ToInt32(Session["userID"]);
try
{
using (HrDcpDBContainer db = new HrDcpDBContainer())
{
var leave = db.leaves.Create();
leave.dateFrom = mv.DateFrom;
leave.dateSubmitted = DateTime.Now;
leave.dateTo = mv.DateTo;
leave.nrDays = mv.NrDays;
leave.reason = mv.SpecialLeave;
leave.TLApproval = null;
leave.TLApprovalDate = null;
leave.TLApprovalID = mv.TeamLeaderID;
leave.DMApprovalDate = null;
leave.DMApprovalID = mv.DepManagerID;
leave.DMApproval = null;
leave.type = mv.Type;
leave.user = userId;
db.leaves.Add(leave);
db.SaveChanges();
}
ViewBag.Message = "Leave Form submitted Successfully. You will be redirected shortly...";
return View("result");
}
catch (Exception ex)
{
ViewBag.Message = ex;
//ViewBag.Message = "Leave Form submitted Successfully. You will be redirected shortly...";
return View("result");
}
The problem comes in leave.user = userId;. It says:
Cannot implicitly convert int to Portal.Model.user
I can't seem to find out how to do this...
You're telling it to put the UserId where your leave model is asking for a User.
Your relationship requires a User to go in there, so you'll have to update your code a little bit:
using (HrDcpDBContainer db = new HrDcpDBContainer())
{
var leave = db.leaves.Create();
leave.user = db.users.First(x => x.Id == userId);
}
This will put reference to the actual user in the new leave record. If you go later and check it out you'll see a column in the leave table called user_Id that has an integer value in it and is set as a foreign key to the users table.
Note that this will error if no user exists having the specified Id value. If you anticipate this to be a problem, rather use .FirstOrDefault() instead of .First() and then account for the value being null before you add it to your new leave object.
That's expected since User is a object and not int. What you should be doing probably is leave.user.UserId = userId; instead [Assuming leave.user is of type User which has a UserId property]
When I'm editing a "salesmember" and I'm trying to save the new file path / or old file path, based on user input, it should either overwrite the image, or it will use the previous image stored in the DB.
But, when I try to modify the entity state, before I save the changes in my SQL Server, I get the error:
An exception of type 'System.InvalidOperationException' occured in EntityFramework.dll but was not handled in user code. Additional information: Attaching an entity of type 'SalesMember' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.
I'm modifying the SalesMember with that primary key. Which, it saves the image locally, but it won't save the DB row.
My Edit Action -----
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="SalesMemberID,FirstName,LastName,PageName,CellPhone,Email,InactiveRedirectTo,CustomText,Photo,Active, Position")] SalesMember salesmember, HttpPostedFileBase file)
{
SalesMember SalesPhoto = db.SalesMembers.Find(salesmember.SalesMemberID);
salesmember.Photo = saveImage(file, salesmember, SalesPhoto);
if (ModelState.IsValid)
{
salesmember.AddDate = SalesPhoto.AddDate;
salesmember.UpdateDate = DateTime.Now;
salesmember.IPAddress = Request.UserHostAddress;
salesmember.AddUser = "admin";
salesmember.UpdateUser = "admin";
db.Entry(salesmember).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(salesmember);
}
SalesPhoto Save Function --
private string saveImage(HttpPostedFileBase file, SalesMember salesmember, SalesMember SalesPhoto = null)
{
string photo = "";
string returnPhoto = "";
//File blank
if( file == null )
//If File Path For that User Already In DB, return that File Path
if(! String.IsNullOrEmpty(SalesPhoto.Photo))
return "/Images/no-upload-icon.jpg";
//If File ! empty, Save image uploaded
photo = Server.MapPath("/Images/" + salesmember.PageName.ToString() + ".jpg");
file.SaveAs(photo);
returnPhoto = "/Images/" + salesmember.PageName.ToString() + ".jpg";
return returnPhoto;
}
I believe it has to do with the LINQ Query, as when I remove the LINQ Query & saveImage method and just save the photo with a test path(i.e., "/Images/foo.jpg"), it works.
Thanks in advance.
You can not have two entities (same type) with same primary keys in memory in Entity Framework. salesmember and SalesPhoto if you want to have AddDate in your form Edit, you can Include it as a HiddenField in form, Or
my recommendation is to deal with ViewModels not EF models in views to
ignore these Issues
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="SalesMemberID,FirstName,LastName,PageName,CellPhone,Email,InactiveRedirectTo,CustomText,Photo,Active, Position")] SalesMember salesmember, HttpPostedFileBase file)
{
SalesMember SalesPhoto = db.SalesMembers.AsNoTracking().Find(salesmember.SalesMemberID);
salesmember.Photo = saveImage(file, salesmember, SalesPhoto);
if (ModelState.IsValid)
{
salesmember.AddDate = SalesPhoto.AddDate;
salesmember.UpdateDate = DateTime.Now;
salesmember.IPAddress = Request.UserHostAddress;
salesmember.AddUser = "admin";
salesmember.UpdateUser = "admin";
db.Entry(salesmember).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(salesmember);
}
I have the following scenario:
the below 2 global variables in my page:
MainContext db = new MainContext();
User user = new User();
A method to fill the properties that is called on the button update:
private void FillProperties()
{
user.FirstName = txtFirstName.Text;
user.LastName = txtLastName.Text;
user.Email = txtEmail.Text;
}
on the button update i am doing the following:
FillProperties();
user.ID = Request.QueryString("userid");
db.SaveChanges();
but the record isn't been updated which i think is logical since the user variable isn't related to db object, but i a, not being able to do this:
db.Users.AddObject(user);
since AddObject isn't found in the db properties.
What can I do to update user?
Your answers are appreciated.
If you are using the DbContext API simply use
db.Entry(user).State = EntityState.Modified;
Where do you add your user to the DB?
If the user exists in the DB, in order to update it, you should do, for example:
user = db.Users.Where(x => x.ID == Request.QueryString("userid")).Single();
FillProperties();
db.SaveChanges();
I'm trying to save an entity to my database using this code:
public void Add(object entity)
{
DbContext.Entry(entity).State = System.Data.EntityState.Added;
DbContext.SaveChanges();
}
I tested and if something is wrong (e.g. a field of the entity is null that can't be null in the datbase) it gives an error. I filled in all the necesarry fields and called this code. It did not give an error. However, the entity also didn't get added to the database. How can I find out where DbContext.SaveChanges(); goes wrong without an error message?
Below is the code that calls the Add() function.
public void StoreElectronicSignatureType(ElectronicSignatureTypeModel model)
{
var RSA = new System.Security.Cryptography.RSACryptoServiceProvider();
var parameters = RSA.ExportParameters(false);
model.modulus = Convert.ToBase64String(parameters.Modulus);
model.exponent = Convert.ToBase64String(parameters.Exponent);
model.privatekey = RSA.ToXmlString(true);
ElectronicSignatureType electronicSignatureType = new ElectronicSignatureType();
Entity entity = GetEntity(model.entity);
electronicSignatureType.Entity = entity;
electronicSignatureType.HashAlgorithm = model.hashAlgorithm;
electronicSignatureType.Exponent = model.exponent;
electronicSignatureType.Modulus = model.modulus;
electronicSignatureType.Version = model.version;
//electronicSignatureType.EntityId = entity.EntityId;
electronicSignatureType.PrivateKey = StrToByteArray(model.privatekey);
Add(electronicSignatureType);
}
You have to attach the new entity to the context. Try:
context.ElectronicSignatureTypes.Add(electronicSignatureType);
context.SaveChanges();
My create and delete operations are working well. But, the Edit function is giving the following error :- Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
NOTE:- CatPicView is a ViewModel merging the two entities Category and Picture
Following is the code for my Edit action code :-
[HttpPost]
public ActionResult Edit(CatPicView catPic)
{
if (ModelState.IsValid)
{
if (!String.IsNullOrEmpty(catPic.Picture.PictureUrl))
{
if (catPic.Category.PictureId == null)
{
Picture picture = new Picture();
picture.PictureUrl = catPic.Picture.PictureUrl;
db.Pictures.Add(picture);
catPic.Category.PictureId = picture.Id;
}
else
{
db.Entry(catPic.Picture).State = EntityState.Modified;
}
}
db.Entry(catPic.Category).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ParentCategoryId = new SelectList(db.Categories, "Id", "Name", catPic.Category.ParentCategoryId);
return View(catPic);
}
Using the debuger, check the properties of the object you are trying to update. The most likely is that you have an ID in null.
To fix this, you should place a hidden field holding the id of the modified object so when posting the form it became mapped to your object.
You are using an ID that does not exist in the current context which is picture.Id. At the time that you are using it an ID has not yet been generated, add db.SaveChanges before attempting to use the ID.
if (catPic.Category.PictureId == null)
{
Picture picture = new Picture();
picture.PictureUrl = catPic.Picture.PictureUrl;
db.Pictures.Add(picture);
db.SaveChanges();
catPic.Category.PictureId = picture.Id;
}