Simple.Data - Primary Key Mapping - simple.data

i'm using Simple.Data and I have a question about.
I have the following classes:
public abstract class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string Salt { get; set; }
}
public class Customer : User
{
public string Email { get; set; }
}
public class Admin : User
{
public string Name { get; set; }
public bool IsActive{ get; set; }
}
And a class that makes the actions in database:
public class Manager
{
public string ConString { get; set; }
public Manager()
{
ConString = ConfigurationManager.ConnectionStrings["Test"].ConnectionString;
}
public void CustomerUpdate()
{
var obj = new Customer()
{
Id = 1,
Username = "teste",
Password = "teste",
Salt = "",
Email = "teste#teste.com"
};
var db = Database.OpenConnection(conString);
db.tbCustomer.Update(obj);
}
public void AdminUpdate()
{
var obj = new Admin()
{
Id = 1,
Username = "teste",
Password = "teste",
Salt = "",
Name = "teste",
IsActive = true
};
var db = Database.OpenConnection(conString);
db.tbAdmin.Update(obj);
}
}
But, i have a problem:
In my db, in the table tbCustomer, the Primary Key is the "CustomerId" column. And the Primary Key of the table tbAdmin is the "AdminId" column.
As the User class has a property called "Id", I can not do updates.
Is there any way I map for when you're giving update on tbCustomer table, the system take "Id" property and enter the "CustomerId" column?
Same for tbAdmin. I want him to take "Id" and place in "AdminId".

If you can't rename the property in your class the best option is most likely to use Named Parameters in your update instead of passing the object. An example for yours would be
db.tbCustomer.UpdateById(Id: 1,
Username: "teste",
...);

Related

The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.ConsoleUserInfoes_dbo.ConsolesCheckBoxes_consoleId"

I'm getting this error:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.ConsoleUserInfoes_dbo.ConsolesCheckBoxes_consoleId". The conflict occurred in database "aspnet-ForePlay-20180525122039", table "dbo.ConsolesCheckBoxes", column 'ConsoleId'.
I'm using Entity Framework and ASP.NET MVC 5 and IdentityUser and try to insert data form checkListBox to table into my database.
This is happening on the register view, when user need to register and fill the form.
public class ConsoleUserInfo
{
[Key]
public int identity { get; set; }
[Required]
[StringLength(255)]
[ForeignKey("User")]
public string userid { get; set; }
[Required]
[ForeignKey("consolesCheckBox")]
public int consoleId { get; set; }
public virtual ApplicationUser User { get; set; }
public virtual ConsolesCheckBox consolesCheckBox { get; set; }
}
This is the table that need to get a user id (form applictionUser) and consoleId
(form ConsolesCheckBox )
This is the ApplicationUserUser model class:
public class ApplicationUser : IdentityUser
{
[Required]
[StringLength(255)]
override
public string UserName { get; set; }
[Required]
[StringLength(50)]
public string Phone { get; set; }
public byte[] UserPhoto { get; set; }
public virtual UserAddress Address { get; set; }
public virtual ICollection<ConsolesCheckBox> consoleCheckBox { get; set; }
}
and this is the checkBoxList table:
public class ConsolesCheckBox
{
[Key]
public int ConsoleId { get; set; }
public string ConsoleName { get; set; }
public bool IsChecked { get; set; }
public virtual ICollection<ApplicationUser> ApplicationUser { get; set; }
}
This is my account controller, all in the register get and post
// GET: /Account/Register
[AllowAnonymous]
public ActionResult Register()
{
//using database
using (ApplicationDbContext dbo = new ApplicationDbContext())
{
//data will save list of the consoleCheckBoxItem
var data = dbo.consolesCheckBox.ToList();
// because the view is request a common model, we will create new one
CommenModel a = new CommenModel();
a.ConsolesCheckBoxList = data;
// we will need to return common model, that way we will return a
return View(a);
}
}
//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register([Bind(Exclude = "UserPhoto")]CommenModel model)
{
if (ModelState.IsValid)
{
// To convert the user uploaded Photo as Byte Array before save to DB
byte[] imageData = null;
if (Request.Files.Count > 0)
{
HttpPostedFileBase poImgFile = Request.Files["UserPhoto"];
using (var binary = new BinaryReader(poImgFile.InputStream))
{
imageData = binary.ReadBytes(poImgFile.ContentLength);
}
}
var user = new ApplicationUser
{
UserName = model.registerViewModel.Email,
Email = model.registerViewModel.Email,
Phone = model.registerViewModel.Phone
};
user.UserPhoto = imageData;
var result = await UserManager.CreateAsync(user, model.registerViewModel.Password);
//after the user create, we will use the id and add the id to the userAddress table include
// Address, longitude and latitude.
using (ApplicationDbContext dbo = new ApplicationDbContext())
{
var currentUserId = user.Id;
var pasinfo = dbo.userAddress.FirstOrDefault(d => d.Userid == currentUserId);
if (pasinfo == null)
{
pasinfo = dbo.userAddress.Create();
pasinfo.Userid = currentUserId;
dbo.userAddress.Add(pasinfo);
}
pasinfo.Address = model.useraddress.Address;
pasinfo.latitude = model.useraddress.latitude;
pasinfo.longitude = model.useraddress.longitude;
dbo.SaveChanges();
foreach (var item in model.ConsolesCheckBoxList.Where(x => x.IsChecked).Select(x => x.ConsoleId))
{
var consoleUserInfo = new ConsoleUserInfo
{
userid = currentUserId,
consoleId = item
};
dbo.consoleUserInfo.Add(consoleUserInfo);
}
dbo.SaveChanges();
}
}
}
In the register GET I have a common model, because I used 3 models in the view
this is the common model:
public class CommonModel
{
public UserAddress useraddress { get; set; }
public RegisterViewModel registerViewModel { get; set; }
public List<ConsolesCheckBox> ConsolesCheckBoxList { get; set; }
}
I need your help here, I've been trying to fix this all day.

Calling UserManager.AddToRole erases user password?

I am fairly new to MVC5/ASP.NET Identity and I have found an issue that has stumped me a bit.
I am writing a small form for my ASP.NET MVC5 application that will allow an admin user (member of the Admins role) to review the users that have signed up to the site and edit the details of and assign roles to those users. When the form is submitted, if a role has been assigned to the user the UserManager.AddToRole method is called.
I noticed after this that once this is done, that user is then unable to log into the application. Looking in the database, it appears when AddToRole is called, the PasswordHash field is set to null. Is this normal and if not how to I get around this issue?
For reference my relevant code is below
Controller
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Admin")]
public ActionResult Details(EditUserViewModel model)
{
model.Save();
return RedirectToAction("List", "Account");
}
Relevant view models
public class EditUserViewModel
{
public string UserId { get; set; }
public string UserName { get; set; }
[Required]
[StringLength(255)]
[Display(Name = "Email address")]
public string Email { get; set; }
[StringLength(255)]
[Display(Name = "First name")]
public string FirstName { get; set; }
[StringLength(255)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[StringLength(255)]
[Display(Name = "Mobile Number")]
public string MobileNumber { get; set; }
public IList<EditUserRolesViewModel> UserRoles { get; set; }
public void Save()
{
using (ApplicationDbContext context = new ApplicationDbContext())
{
ApplicationUser user = new ApplicationUser()
{
Id = this.UserId,
UserName = this.UserName,
Email = this.Email,
FirstName = this.FirstName,
LastName = this.LastName,
MobileNumber = this.MobileNumber
};
context.Users.Attach(user);
context.Entry(user).Property(x => x.Email).IsModified = true;
context.Entry(user).Property(x => x.FirstName).IsModified = true;
context.Entry(user).Property(x => x.LastName).IsModified = true;
context.Entry(user).Property(x => x.MobileNumber).IsModified = true;
context.SaveChanges();
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
foreach (var row in this.UserRoles)
{
if (row.RowChanged)
{
if (row.RoleAssigned)
{
UserManager.AddToRole(this.UserId, row.RoleName);
}
else
{
UserManager.RemoveFromRole(this.UserId, row.RoleName);
}
}
}
}
}
}
public class EditUserRolesViewModel
{
public string RoleId { get; set; }
[Display(Name = "Role name")]
public string RoleName { get; set; }
[Display(Name = "Assigned")]
public bool RoleAssigned { get; set; }
public bool RowChanged { get; set; }
}
As I see from your code, you have attached partially initialized object user to context.Users. As a result when UserManager gets control: AddToRole, it tries to update Database. And you'll have lot empty or null fields in the current users row.
You can fix doing any of the following (both will help):
instead of
ApplicationUser user = new ApplicationUser() use user = UserManager.FindById(UserId)
after assigning values from viewmodel EntityFramework will take care of modified fields.
use another context when dealing with roles
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));

Identity framework - how to join another profile table by UserID

I have set Identity so I have separate table for user profile data (firstname, lastname etc.).
Problem is that I have joined those tables via Email field.
I want to change this so I can connect tables by UserID instead.
What I need is to get new userID for created user and use that as foreign key to UserProfileInfo object.
public class ApplicationUser : IdentityUser<int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
{
public string Email { get; set; }
public string ConfirmationToken { get; set; }
public bool IsConfirmed { get; set; }
public virtual UserProfileInfo UserProfileInfo { get; set; }
}
public class UserProfileInfo
{
public int Id { get; set; }
public string EmailId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
When I create new user I have:
var user = new ApplicationUser()
{
UserName = model.UserName,
Email = model.Email,
ConfirmationToken = confirmationToken,
IsConfirmed = false,
UserProfileInfo = new UserProfileInfo { EmailId = model.Email }
};
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
SendEmailConfirmation(model.Email, model.UserName, confirmationToken);
return RedirectToAction("RegisterStepTwo", "Account");
}
else...
Why are you doing a join in the first place? ApplicationUser is your user, and the whole point of inheriting from IdentityUser is to allow you extend the user object. Just put your properties like FirstName and LastName directly on ApplicationUser.

SQLite table without Primary Key but Why generate record for each update

I create a SQlite Table without primary key using Class as follow. But Each time I update, SQLite keeps generating record for each update. It should override the same record which it was first created but should not generate record for each update.
Thanks.
Not adding this to the class: [PrimaryKey, AutoIncrement]
class NetworkCredential
{
public string WebServiceName { get; set; }
public string WebServer { get; set; }
public int Port { get; set; }
public string Company { get; set; }
public int DefaultCredential { get; set; }
}
using (var db = new SQLite.SQLiteConnection(DBPath))
{
var User = db.Query("Select * From NetworkCredential").FirstOrDefault();
if (User != null)
{
User.WebServiceName = txtWebServer.Text.Trim();
User.WebServer = txtWebServer.Text.Trim();
User.Port = Convert.ToInt32(txtPort.Text);
int success = db.InsertOrReplace(User);
}
else
{
int success = db.Insert(new NavNetworkCredential()
{
WebServer = txtWebServer.Text.Trim(),
WebServiceName = txtWebServiceName.Text.Trim(),
Port = Convert.ToInt32(txtPort.Text)
});
}

asp.net mvc querying from different table to view

I need to query data from 2 table
public class UserProfile
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Name { get; set; }
}
and
public class PrivateMessage
{
public int MessageId { get; set; }
public string Sender { get; set; }
public string Receiver { get; set; }
public string Subject { get; set; }
public string Message { get; set; }
private DateTime _date = DateTime.Now;
public DateTime sentDate { get { return _date; } set { _date = value; } }
}
and this what i tried on my controller
public ActionResult Index()
{
var x = User.Identity.Name;
var query = from p in db.PrivateMessages
join u in db.UserProfiles on p.Sender equals u.UserName
where p.Receiver == x
select new
{
u.UserName,
u.Name,
p.Receiver,
p.Subject,
p.Message,
p.sentDate
};
return View(query);
}
this is my view model
#model IEnumerable<SeedSimple.Models.PrivateMessage>
but i got this error
The model item passed into the dictionary is of type
'System.Data.Entity.Infrastructure.DbQuery1[<>f__AnonymousType95[System.String,System.String,System.String,System.String,System.DateTime]]',
but this dictionary requires a model item of type
'System.Collections.Generic.IEnumerable`1[SeedSimple.Models.PrivateMessage]'.
all i want is to get username and name from UserProfile table and receiver, subject, message and sentDate on PrivateMessage table
Well you're passing as a Model an anonymous type yet you have a strongly typed View.
You can either create a new ViewModel that contains all the fields you're using for your query and pass that, or you can pass all the properties in the ViewBag (not a pretty solution).
EDIT
Thought I'd give you an example.
Here is a ViewModel containing the data you need:
public class MessageViewModel
{
public string UserName { get; set; }
public string Name { get; set; }
public string Receiver { get; set; }
public string Subject { get; set; }
public string Message { get; set; }
public DateTime SentDate { get; set; }
}
In your view:
#model IEnumerable<SeedSimple.Models.MessageViewModel>
In your Controller:
public ActionResult Index()
{
var x = User.Identity.Name;
var result = from p in db.PrivateMessages
join u in db.UserProfiles on p.Sender equals u.UserName
where p.Receiver == x
select new MessageViewModel
{
UserName = u.UserName,
Name = u.Name,
Receiver = p.Receiver,
Subject = p.Subject,
Message = p.Message,
SentDate = p.sentDate
};
return View(result);
}
I hope this helps.

Resources