MVC4 Entity Framework and Simplemembership Re-Creation - asp.net-mvc

Ok so I'm adding on to the Simplemembership.
Model UsersProfiles
namespace OilNGasWeb.Models
{
[Table("Users")]
public class UserProfiles
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public string Initials { get; set; }
public string Company { get; set; }
public string Department { get; set; }
public string Title { get; set; }
public string Team { get; set; }
public string TeamSub { get; set; }
public string Phone { get; set; }
public string ImageLocation { get; set; }
public string CurrentlyAuthorized { get; set; }
public string Note { get; set; }
public string Comment { get; set; }
//public virtual dbClient Client { get; set; }
public virtual ICollection<Roles> Roles { get; set; } //many to many
public virtual ICollection<dbClient> Clients { get; set; } // many to many
}
}
Roles
namespace OilNGasWeb.Models
{
[Table("webpages_Roles")]
public class Roles
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
[Required(ErrorMessage = "Required")]
public int RoleID { get; set; }
[Required(ErrorMessage = "Required")]
public string RoleName { get; set; }
public virtual ICollection<UserProfiles> UserProfiles { get; set; } //many to many
}
}
My issue now that i have it creating the many to many tables like i saw it creat before modifications my question is how to get those tables Renamed
webpages_UsersInRoles
I would prefer not to go into SSMS and change them physically rather tell MVC to use a different instance
From the code above EF produced RolesUserProfiles instead of webpages_UsersInRoles
The error shows when the program is trying to #if (User.IsInRole("Administrator")) validade user.
Naturally I hit F12 on IsInRole to bring me to the definition....
it does but there all empty
Now what ? how can i recode if its hidden from me ? where is the code at , and how can i Modify this?
What i would like out of all this is
either renaming the tables ManytoMany as they are being created
being able to modify the code that looks for webpages_UsersInRoles
Thanks in advance.

You cannot rename the tables. The table names are hard coded in SimpleMembership. You can see the source code here:
http://aspnetwebstack.codeplex.com/SourceControl/latest#src/WebMatrix.WebData/SimpleMembershipProvider.cs
Don't use the EF navigational properties. You should be accessing this information via the Membership or WebSecurity API's.
If you really want to do this, then you will need to configure EF to use the tablenames required by simple membership, which means utilizing the fluent mapping syntax.. which is not exactly intuitive.

Related

Error while creating 1-to-1 relationship between two classes in Entity Framework

I'm trying to create 1-to-1 relationship between two classes. 1 user has 1 profile picture and 1 profile picture belongs to one user.
the code is as follows.
public class UserImage
{
[Key, ForeignKey("User")]
public int ImageId { get; set; }
public byte [] ImageContentBytes { get; set; }
public string FileName { get; set; }
public string UserId { get; set; }
public string ImagePath { get; set; }
[InverseProperty("UserImage")]
public virtual ApplicationUser User { get; set; }
}
public class ApplicationUser : IdentityUser
{
public string FullName { get; set; }
public string Address { get; set; }
public string Postcode { get; set; }
public string RoleId { get; set; }
public IdentityRole Role { get; set; }
public int CityId { get; set; }
public ICollection<User_Has_Jobs_Posted> UserJobs { get; set; }
public City City { get; set; } // Adding relationship to the user.
public IList<JobPost> jobPosts { get; set; }
[InverseProperty("User")]
public virtual UserImage UserImage { get; set; }
}
The error is saying:
Unable to determine the principal end of an association between the types 'FinalWorkFinder.Models.UserImage' and 'FinalWorkFinder.Models.ApplicationUser'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
In a one-to-one relationship one entry must depend on another, rather then both entries depending on each other.
So in your case an ApplicationUser entry would be valid on its own but a UserImage cannot.
You can fix this by using the Required attribute on the FK like so:
[Required]
public virtual ApplicationUser User { get; set; }
Or you could use fluent api, and do something along the lines of:
modelBuilder.Entity<ApplicationUser>()
.HasOptional(f => f.UserImage)
.WithRequired(s => s.User);

ASP.NET MVC EF 6: define a lookup table/model

i am trying to define a database model in code-first to see and display which user is assigned as a specialist for the record data.
I have a very simple model for the user:
public class User
{
public int ID { get; set; }
public string userName { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
....
}
Next I have defined two (simple) models which define the data that can be edited by the user and the specialist should be assigned to using a dropdownlist:
public class Order
{
public int ID { get; set; }
public string orderNumber { get; set; }
public int specialistID { get; set; }
public virtual User specialist{ get; set; }
}
public class Part
{
public int ID { get; set; }
public string partNumber { get; set; }
public string description { get; set; }
public int specialistID { get; set; }
public virtual User specialist{ get; set; }
}
What kind of relation between the models can be used without having a navigation property for each table in the User model?
Do I need to use additional tables to define the relationship: User.Id-Order.specialistID and the relationship: User.Id-Part.specialistID ?
Is there a smarter way out-of-the-box by Entity Framework?
Many thanks for your answers.
Pascal
By default when you add forign-key constraint to the many-to-one table the Entity Framework add virtual property to the entity class and virtual ICollection to the User.

How to overide PasswordInAsync for ASP.NET MVC?

We have this unique requirement to login to MVC ASP.NET app by adding extra "Tenant Code" next to Username/email and password.
We've created a few class below:
public class UserProfile
{
public Guid Id { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
public String Address { get; set; }
public String Postcode { get; set; }
public String State { get; set; }
public String LandLineNo { get; set; }
public String MobileNo { get; set; }
public Tenant Tenant { get; set; }
}
public class Tenant
{
public Guid Id { get; set; }
public String Code { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public Boolean IsActive { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime LastDateModifiedDate { get; set; }
}
We've added properties in class ApplicationUser : IdentityUser
public virtual UserProfile UserProfile { get; set; }
and added on class ApplicationDbContext : IdentityDbContext
public System.Data.Entity.DbSet<UserProfile> UserProfile { get; set; }
The only that we can think of is to override the SignInManager.PasswordSignInAsync is that right? How to achieve this?
I'm appreciated your input.
Thanks
I don't think overriding the PasswordSignInAsync is going to be useful since its signature doesn't take over the user entity. It only takes over username, password, isPersistent & shouldLockout so you don't have any access to any tenant info. If you tried to check for the tenant info buy the username you may end up with multple accounts.
I would recommend creating your own method in a class that derives from the SignInManager. Get this to check the user and tenant info and call SignInAsync or SignInOrTwoFactor (if you're using 2 factor auth).
If you get a bit lost, have a look at the Microsoft.AspNet.Identity.Owin assembly, in your decompiler of choice, and check what those methods are doing.

Entity framework migration of Collections

I have a model that looks like this
public abstract class Item
{
public int ItemId { get; set; }
public String Title { get; set; }
public String Description { get; set; }
public DateTime PurchaseDate { get; set; }
public ICollection<String> Pictures { get; set; }
public Int32 MinimumPrice { get; set; }
public DateTime Deadline { get; set; }
public Boolean VisibleBids { get; set; }
public Boolean Handled { get; set; }
public DateTime PlacementDate { get; set; }
public ApplicationUser User { get; set; }
}
In my controller I do
db.Items.ToList()
This leaves the Pictures field for all fetched objects null because its how the entity framework works. What is a good solution to fetch them in one query?
I hope you already done with Navigation properties between your tables, Now you just need to make your collection virtual and use the concept of eager loading when you need data from both the tables
public virtual ICollection<String> Pictures { get; set; }
and use include in linq like
db.Items.Include("Pictures").ToList()
So here by making virtual navigation you are saying that only take the data of related entity when you needed and whenever you need the data use the Include for eager loading.
For setting navigation properties please have a look on the code.
Suppose the scenario where we have a Post and on this we have multiple comments like
class Posts
{
public int PostsId { get; set; }
public string PostsDescription { get; set; }
public virtual ICollection<Comments> Comments { get; set; }
}
class Comments
{
public int CommentsId { get; set; }
public string CommentsDescription { get; set; }
public int PostsId { get; set; }
public virtual Posts Posts { get; set; }
}

EF Code First Foreign Key's

I am working with the EF Code First library trying to work on an appointment scheduling app.
The model's I have are going to be a Client, Appointment, and AppointmentType...
Basically each Client can have a set of Appointments, and each Appointment can have a single AppointmentType...
The code is as follows:
public class Client
{
[ScaffoldColumn(false)]
public int ClientID { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[EmailAddress]
[Required]
public string Email { get; set; }
[DataType("DateTime")]
public DateTime Birthday { get; set; }
[Required]
public string CellPhone { get; set; }
public string HomePhone { get; set; }
public string Notes { get; set; }
public virtual ICollection<Appointment> Appointments{ get; set; }
public string Name {
get{
return FirstName + " " + LastName;
}
}
public class Appointment
{
[ScaffoldColumn(false)]
public int AppointmentID { get; set; }
[ScaffoldColumn(false)]
public int ClientID { get; set; }
[ScaffoldColumn(false)]
public int AppointmentTypeID { get; set; }
[Required]
public DateTime AppointmentDate { get; set; }
public string Notes { get; set; }
public virtual AppointmentType AppointmentType { get; set; }
public virtual Client Client { get; set; }
}
public class AppointmentType
{
[ScaffoldColumn(false)]
public int AppointmentTypeID { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
public virtual Appointment Appointment { get; set; }
}
Everything works well when I create an appointment type, and a client, but when I create an appointment I get the following error...
InnerException {"The INSERT statement conflicted with the FOREIGN KEY constraint \"Appointment_Client\". The conflict occurred in database \"Salon.Models.SalonContext\", table \"dbo.Clients\", column 'ClientID'.\r\nThe statement has been terminated."} System.Exception {System.Data.SqlClient.SqlException}
If more details are needed, please let me know...I am just trying to figure out if I am missing anything in the setup.
This is what happens when I debug on the post to create the Appointment...All the ID's are as 0 which is correct, but should the other fields not be null?? Or does it matter...Just not very familiar with how things should look this being my first EF Code First project...
According to your setup, one AppointmentType can only have one Appointment. This is a one-to-one mapping. In this case, you better move the AppointmentType into the Appointment entity. Otherwise, what I believe is more logical, an AppoitmentType can have many Appointments but one Appointment can have only one AppointmentType. Accordingly, you should have a virtual ICollection inside your AppointmentType entity.
public class AppointmentType
{
[ScaffoldColumn(false)]
public int AppointmentTypeID { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Appointment> Appointments { get; set; }
}
I am not sure this is what's causing the problem but it could be. Sometimes mapping faults cause some weird exceptions to be thrown. Give it a try and let me know if your problem gets resolved.
By your constraints AppointmentType and Client cannot be null in Appointment. You can delete constraints or set correct objects in object properties. For example create Client and AppointmentType and then create Appointment for created Client with created AppointmentType

Resources