My application was working fine until I added 3 new classes(Administrator,Department and Depot) and altered the IssueContext.cs in the Data Access Layer.
Since my IssueContext has been altered I needed to update my database so I used update-database in the Package Manager Console then I got this(Open tab in the new window)
Which is weird because it was working perfectly fine before. I then installed Entity Framework then update-database worked.
However when I click on my User tabs or About tabs they give me a "Webpage not available" but the Index page works. Could this be a relational database mapping problem where I didn't map my new classes correctly?
Note: I also tried installing MVC but MVC Razor just crashes everything.
Here's my Entity Diagram
User.cs
public class User
{
public int UserID { get; set; }
[StringLength(50, MinimumLength = 1)]
public string LastName { get; set; }
[StringLength(50, MinimumLength = 1, ErrorMessage = "First name cannot be longer than 50 characters.")]
[Column("FirstName")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; }
public string FullName
{
get { return LastName + ", " + FirstMidName; }
}
public int AdministratorID { get; set; }
[ForeignKey("AdministratorID")]
public virtual Administrator Administrator { get; set; }
public int DepartmentID { get; set; }
[ForeignKey("DepartmentID")]
public virtual Department Department { get; set; }
public int DepotID { get; set; }
[ForeignKey("DepotID")]
public virtual Depot Depot { get; set; }
public int TicketID { get; set; }
//Setting up relationships A use can apply for any number of tickets, so Tickets is defined as a collection of Ticket entities.
public virtual ICollection<Ticket> Users { get; set; }
}
Ticket.cs
public class Ticket
{
public string Issue { get; set; }
[DisplayFormat(NullDisplayText = "No Priority")]
public Priority? Priority { get; set; }
//Category One to Many Ticket
public int CategoryID { get; set; }
[ForeignKey("CategoryID")]
public virtual Category Category { get; set; }
//User (One to Many) Ticket
public int UserID { get; set; }
public int TicketID { get; set; }
[ForeignKey("TicketID")]
public virtual User User { get; set; }
public int AdminID { get; set; }
public virtual ICollection<Administrator> Administrators { get; set; }
}
Depot.cs
public class Depot
{
public int DepotID { get; set; }
[StringLength(50, MinimumLength = 3)]
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
}
Department.cs
public class Department
{
public int DepartmentID { get; set; }
[StringLength(50, MinimumLength = 3)]
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
}
Category.cs
public class Category
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CategoryID { get; set; }
public string Title { get; set; }
public virtual ICollection<Ticket> Tickets { get; set; }
}
Administrator.cs
public class Administrator
{
[Key, ForeignKey("User")]
public int UserID { get; set; }
public int AdminID { get; set; }
public int TicketID { get; set; }
[StringLength(50)]
public string AdminRole { get; set; }
public virtual ICollection<Ticket> Tickets { get; set; }
public virtual User User { get; set; }
}
Context.cs
public class IssueContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Ticket> Tickets { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Administrator> Administrators { get; set; }
public DbSet<Depot> Depots { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Ticket>()
.HasMany(c => c.Administrators).WithMany(i => i.Tickets)
.Map(t => t.MapLeftKey("TicketID")
.MapRightKey("AdministratorID")
.ToTable("AdministratorsTickets"));
modelBuilder.Entity<Administrator>()
.HasKey(e => e.UserID);
modelBuilder.Entity<User>()
.HasOptional(s => s.Administrator) // Mark StudentAddress is optional for Student
.WithRequired(ad => ad.User); // Create inverse relationship
}
}
Related
I'm still studying Entity Framework and tried to create a model including the foreign keys.
But when I tried to migrate the code, I got this error
Introducing FOREIGN KEY constraint 'FK_dbo.QuestionResults_dbo.QuestionsTables_QuetionsTableId' on table 'QuestionResults' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints
These are my model classes:
public class MainDetails
{
[Key]
public int Id { get; set; }
public string Language { get; set; }
[Required]
public string CustomerName { get; set; }
[Required]
public string ContactNumber { get; set; }
public string EmailAddress { get; set; }
[DisplayName("Service Type")]
[ForeignKey("QuestionsTable")]
public int ServiceTypeId { get; set; }
public virtual QuestionsTable QuestionsTable { get; set; }
[Required]
public string VehicleNumber { get; set; }
[Required]
public string ServiceLocation { get; set; }
public string Suggestion { get; set; }
public bool Status { get; set; } = true;
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Created Date")]
public DateTime CreatedDate { get; set; } = DateTime.Now;
public virtual QuestionResults QuestionResults { get; set; }
public virtual IList<QuestionResults> QuestionResultsMainlist { get; set; }
public virtual IList<QuestionsTable> QuestionsTables { get; set; }
}
public class QuestionsTable
{
[Key]
public int Id { get; set; }
public string ServiceType { get; set; }
public string Question { get; set; }
public virtual IList<MainDetails> MainDetailsServiceType { get; set; }
public QuestionsTable()
{
MainDetailsServiceType = new List<MainDetails>();
}
}
public class QuestionResults
{
[Key]
public int Id { get; set; }
[DisplayName("MainDetail ID")]
[ForeignKey("MainDetails")]
public int MainDetailsId { get; set; }
public virtual MainDetails MainDetails { get; set; }
[DisplayName("MainDetail ID")]
[ForeignKey("QuestionsTable")]
public int QuetionsTableId { get; set; }
public virtual QuestionsTable QuestionsTable { get; set; }
[Required]
public string CustoAnswer { get; set; }
}
This is the table structure I wanted to create:
To resolve this you can use the EF Model Builder
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<QuestionsTable>()
.HasRequired(a => a.MainDetails)
.WithOptionalDependent()
.WillCascadeOnDelete(false); //This is the important row
}
You'll have to play around with the type of relationship you would like along with whether you specify explicitly the foreign key. If you haven't seen this model builder before have a read here: https://learn.microsoft.com/en-us/ef/core/modeling/
Upon breaking your scenario down I noticed some "oddities". I reduced the noise in the domain model to from your example to this
public class MainDetails
{
[Key]
public int Id { get; set; }
[ForeignKey("QuestionsTable")]
public int ServiceTypeId { get; set; }
public virtual QuestionsTable QuestionsTable { get; set; }
public virtual QuestionResults QuestionResults { get; set; }
public virtual IList<QuestionResults> QuestionResultsMainlist { get; set; }
public virtual IList<QuestionsTable> QuestionsTables { get; set; }
}
public class QuestionsTable
{
[Key]
public int Id { get; set; }
public string ServiceType { get; set; }
public string Question { get; set; }
public virtual IList<MainDetails> MainDetailsServiceType { get; set; }
}
public class QuestionResults
{
[Key]
public int Id { get; set; }
[ForeignKey("MainDetails")]
public int MainDetailsId { get; set; }
public virtual MainDetails MainDetails { get; set; }
[ForeignKey("QuestionsTable")]
public int QuetionsTableId { get; set; }
public virtual QuestionsTable QuestionsTable { get; set; }
}
I few things I noted.
MainDetails contains both One-To-Many (QuestionTable) and Many-To-Many (IList) relationships? I'm unsure on your intention
QuestionsResults contains singular relationships to both entities which aren't replicated in the QuestionTable class? that's fine if it's intentional
ServiceType is a string in QuestionsTable but you are expecting an int as the foreign key in MainDetails?
I am unable to save data using code first technique.
here is my context:
public virtual DbSet<Users> User { get; set; }
public virtual DbSet<Agency> Agencies { get; set; }
public virtual DbSet<ColdStorage> ColdStorages { get; set; }
public virtual DbSet<ShowRoom> ShowRooms { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
and my user model is here:
[Table("Users")]
public class Users
{
[Key]
public int UserId { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
public string Mobile { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public bool isAgency { get; set; }
public bool isColdStorage { get; set; }
public string VerificationCode { get; set; }
public DateTime CreatedDate { get; set; }
// Reverse navigation
public virtual Agency Agency { get; set; }
public virtual ColdStorage ColdStorage { get; set; }
public virtual ShowRoom ShowRoom { get; set; }
public Users()
{
Agency = new Agency();
ColdStorage = new ColdStorage();
ShowRoom = new ShowRoom();
}
}
and my other model is here:
[Table("Agency")]
public class Agency
{
[Key]
public int AgencyId { get; set; }
[ForeignKey("Users")]
public int UserId { get; set; }
public string AgencyName { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Description { get; set; }
public DateTime CreatedDate { get; set; }
[Required]
public virtual Users Users { get; set; }//Foriegn key
}
And the error is here:
Message":"An error has occurred.","ExceptionMessage":"One or more validation errors were detected during model generation:\r\n\r\nColdStorage_Users_Source: : Multiplicity is not valid in Role 'ColdStorage_Users_Source' in relationship 'ColdStorage_Users'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.\r\nShowRoom_Users_Source:
Just like the error says.
"because the Dependent Role properties are not the key properties, the
upper bound of the multiplicity of the Dependent Role must be '*'"
The "Dependent Role properties" here means, eg Agency.UserId, and the "multiplicity must be '*'" means Users must have a collection of Agencies. EG
public virtual ICollection<Agency> Agencies { get; } = new HashSet<Agency>();
I am trying to add an entry to a table that holds a users browsing history information. However, when trying to save the addition an SqlException is thrown:
Cannot insert duplicate key row in object 'dbo.AspNetUsers' with
unique index 'UserNameIndex'. The duplicate key value is
(exampleUserName). The statement has been terminated.
A user is has many browsing histories but a browsing history can only be attached to one user so there is a user as part of the BrowsingHistory DataModel:
namespace DataModels
{
[Table("BrowsingHistory")]
public class BrowsingHistory
{
[Key]
public int BrowsingHistoryId { get; set; }
public int ProductId { get; set; }
public System.DateTime DateTime { get; set; }
public int DeviceId { get; set; }
public int UserId { get; set; }
public virtual AspNetUsers User { get; set; }
public virtual Device Device { get; set; }
public virtual Product Product { get; set; }
}
}
It is to note that I am using the Microsoft Identity classes for my authentication. The user class looks as follows:
namespace DataModels
{
using System;
using System.Collections.Generic;
[Table("AspNetUsers")]
public class AspNetUsers
{
public AspNetUsers()
{
BrowsingHistories = new HashSet<BrowsingHistory>();
Orders = new HashSet<Order>();
AspNetUserClaims = new HashSet<AspNetUserClaims>();
AspNetRoles = new HashSet<AspNetRoles>();
}
[Key]
public int Id { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public bool TwoFactorEnabled { get; set; }
public DateTime? LockoutEndDateUtc { get; set; }
public bool LockoutEnabled { get; set; }
public int AccessFailedCount { get; set; }
public string UserName { get; set; }
public string HouseName { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
public string Town { get; set; }
public string County { get; set; }
public string Postcode { get; set; }
public string ContactNumber { get; set; }
public virtual ICollection<BrowsingHistory> BrowsingHistories { get; set; }
public virtual ICollection<Order> Orders { get; set; }
public virtual ShoppingCart ShoppingCart { get; set; }
public virtual ICollection<AspNetUserClaims> AspNetUserClaims { get; set; }
public virtual ICollection<AspNetRoles> AspNetRoles { get; set; }
}
}
The error occurs when trying to save the addition in the repository. On the _context.SaveChanges() line the method below.
public void CreateBrowsingHistoryEntry(BrowsingHistory bhe)
{
_context.BrowsingHistory.Add(bhe);
_context.SaveChanges();
}
Any help with this issue would be greatly appreciated.
I am trying to implement Asp.net Identity 2.0 with DB first.
I have imported my model.edmx into the project. It contains all the tables I need with the correct information and structure.
In the database there is a table called 'FSKUsers' I have edited this to contain the needed fields of the AspNetUsers which is the default table for Identity 2.0
So in my Identity DB Context I have mapped my FskUser class (which is a high level user for Identity sake)
public class IdentityDbContext : IdentityDbContext<FskUser, FskRole, int, FskUserLogin, FskUserRole, FskUserClaim>
{
public IdentityDbContext()
: base("FSK_FskNetworksEntities")
{
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var userEntity = modelBuilder.Entity<FskUser>();
userEntity.ToTable("FSKUsers", "dbo");
userEntity.Property(p => p.Id).HasColumnName("FSKUserId");
userEntity.Property(p => p.PasswordHash).HasColumnName("Password");
}
public static IdentityDbContext Create()
{
return new IdentityDbContext();
}
}
So basically I want to map the class FskUser to the Data Base table called FSKUser which is also contained in my .edmx model.
When I run the website I get the following error.
The entity type FskUser is not part of the model for the current context
My two POCO classes:
The one from my edmx model:
public partial class FSKUser
{
public FSKUser()
{
this.AspNetUserClaims = new HashSet<AspNetUserClaim>();
this.AspNetUserLogins = new HashSet<AspNetUserLogin>();
this.FSKDevices = new HashSet<FSKDevice>();
this.FSKEventLogs = new HashSet<FSKEventLog>();
this.FSKReports = new HashSet<FSKReport>();
this.FSKTransactions = new HashSet<FSKTransaction>();
this.FSKTriggers = new HashSet<FSKTrigger>();
this.UdlDownloads = new HashSet<UdlDownload>();
this.AspNetRoles = new HashSet<AspNetRole>();
this.FSKCompanies = new HashSet<FSKCompany>();
}
public int FSKUserId { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public string Password { get; set; }
public string SecurityStamp { get; set; }
public bool TwoFactorEnabled { get; set; }
public Nullable<System.DateTime> LockoutEndDateUtc { get; set; }
public bool LockoutEnabled { get; set; }
public int AccessFailedCount { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public byte FSKAccessLevelId { get; set; }
public string AddressStreet1 { get; set; }
public string AddressStreet2 { get; set; }
public string AddressStreet3 { get; set; }
public string AddressPostCode { get; set; }
public Nullable<int> CreatorId { get; set; }
public Nullable<System.DateTime> CreateDate { get; set; }
public string ConfirmationToken { get; set; }
public Nullable<bool> IsConfirmed { get; set; }
public Nullable<System.DateTime> LastPasswordFailureDate { get; set; }
public Nullable<int> PasswordFailuresSinceLastSuccess { get; set; }
public Nullable<System.DateTime> PasswordChangedDate { get; set; }
public string PasswordVerificationToken { get; set; }
public string PasswordVerificationTokenExpirationDate { get; set; }
public bool IsDeleted { get; set; }
public Nullable<int> CostCentreId { get; set; }
public Nullable<int> AdminPasswordResetUserId { get; set; }
public Nullable<System.DateTime> PreviousLogInDate { get; set; }
public System.Guid msrepl_tran_version { get; set; }
public virtual ICollection<AspNetUserClaim> AspNetUserClaims { get; set; }
public virtual ICollection<AspNetUserLogin> AspNetUserLogins { get; set; }
public virtual ICollection<FSKDevice> FSKDevices { get; set; }
public virtual ICollection<FSKEventLog> FSKEventLogs { get; set; }
public virtual ICollection<FSKReport> FSKReports { get; set; }
public virtual ICollection<FSKTransaction> FSKTransactions { get; set; }
public virtual ICollection<FSKTrigger> FSKTriggers { get; set; }
public virtual ICollection<UdlDownload> UdlDownloads { get; set; }
public virtual ICollection<AspNetRole> AspNetRoles { get; set; }
public virtual ICollection<FSKCompany> FSKCompanies { get; set; }
}
The one I use in my Identity Config
public class FskUser : IdentityUser<int, FskUserLogin, FskUserRole, FskUserClaim>
{
[Display(Name = "First Name")]
[Required(ErrorMessage = "First Name is Required.")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
[Required(ErrorMessage = "Last Name is Required.")]
public string LastName { get; set; }
[MaxLength(20)]
[Display(Name = "Cell Number")]
[RegularExpression(#"^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$", ErrorMessage = "Entered phone format is not valid.")]
[StringLength(10, ErrorMessage = "The {0} must be 10 numbers long.", MinimumLength = 10)]
public override string PhoneNumber { get; set; }
[Display(Name = "Access Level")]
public byte? FSKAccessLevelId { get; set; }
[Display(Name = "Street Address 1")]
public string AddressStreet1 { get; set; }
[Display(Name = "Street Address 2")]
public string AddressStreet2 { get; set; }
[Display(Name = "Street Address 3")]
public string AddressStreet3 { get; set; }
[Display(Name = "Postal Code")]
public string AddressPostCode { get; set; }
[Display(Name = "Previous Login")]
public Nullable<DateTime> PreviousLogInDate { get; set; }
[Display(Name = "Account Confirmed")]
public Nullable<bool> IsConfirmed { get; set; }
[Display(Name = "Last Password Failier")]
public Nullable<DateTime> LastPasswordFailureDate { get; set; }
[Display(Name = "Password Last Changed")]
public Nullable<DateTime> PasswordChangedDate { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<FskUser, int> manager)
{
//TODO: add option for web and api (to create different auth types
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
When you use Database first approach with edmx file OnModelCreating method is never called. You may check that with debugger.
I'm trying to write a many-to-many relationship in the override of the onModelCreating method of my context in ASP.NET MVC4. I think I have my classes wrong because I'm getting errors in Intellisense that I don't understand. Here is my override:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Software>().
HasMany(i => i.LocationId).
WithMany(c => c.SoftwareId).
Map(mc =>
{
mc.MapLeftKey("SoftwareId");
mc.MapRightKey("LocationId");
mc.ToTable("SoftwareLocations");
});
}
Here is my Software class:
public class Software
{
public int Id { get; set; }
public virtual List<SoftwareType> SoftwareTypes { get; set; }
public virtual List<Location> Locations { get; set; }
public virtual List<SoftwarePublisher> Publishers { get; set; }
[Required]
[StringLength(128)]
public string Title { get; set; }
[Required]
[StringLength(10)]
public string Version { get; set; }
[Required]
[StringLength(128)]
public string SerialNumber { get; set; }
[Required]
[StringLength(3)]
public string Platform { get; set; }
[StringLength(1000)]
public string Notes { get; set; }
[Required]
[StringLength(15)]
public string PurchaseDate { get; set; }
public bool Suite { get; set; }
public string SubscriptionEndDate { get; set; }
//[Required]
//[StringLength(3)]
public int SeatCount { get; set; }
public virtual Location LocationId { get; set; }
}
Here is my Location class:
public class Location
{
public int Id { get; set; }
[Required]
[StringLength(20)]
public string LocationName { get; set; }
public virtual Software SoftwareId { get; set; }
}
How do I write my Fluent override so I can map them correctly?
Many-to-Many means that in both entities is Collections. So you should set HasMany(software=>software.Locations) and set WithMany(location=>location.Softwares) as in example:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Software>().
HasMany(i => i.Locations).
WithMany(c => c.Softwares).
Map(mc =>
{
mc.MapLeftKey("SoftwareId");
mc.MapRightKey("LocationId");
mc.ToTable("SoftwareLocations");
});
}
Here is my Software class:
public class Software
{
public int Id { get; set; }
public virtual List<SoftwareType> SoftwareTypes { get; set; }
public virtual ICollection <Location> Locations { get; set; }
public virtual List<SoftwarePublisher> Publishers { get; set; }
[Required]
[StringLength(128)]
public string Title { get; set; }
[Required]
[StringLength(10)]
public string Version { get; set; }
[Required]
[StringLength(128)]
public string SerialNumber { get; set; }
[Required]
[StringLength(3)]
public string Platform { get; set; }
[StringLength(1000)]
public string Notes { get; set; }
[Required]
[StringLength(15)]
public string PurchaseDate { get; set; }
public bool Suite { get; set; }
public string SubscriptionEndDate { get; set; }
//[Required]
//[StringLength(3)]
public int SeatCount { get; set; }
}
Here is my Location class:
public class Location
{
public int Id { get; set; }
[Required]
[StringLength(20)]
public string LocationName { get; set; }
public virtual ICollection<Software> Softwares { get; set; }
}