EF Puts wrong relationship in datatabse - c#

I got this project were a Operator can have many roles.
Let me start out with the code so you can see what i mean.
TDOperator:
[DisplayName("Operator")]
public class TDOperator
{
public int TDOperatorId { get; set; }
[DisplayName("First Name")]
[Required]
public string FirstName { get; set; }
[Required]
[DisplayName("Last Name")]
public string LastName { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[DisplayName("Email Adress")]
public string EmailAddress { get; set; }
[Required]
public string Username { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[HiddenInput(DisplayValue = true)]
public DateTime LastLogin { get; set; }
public List<string> RoleNames
{
get
{
return Roles.Select(x => x.Name).ToList();
}
}
public virtual ICollection<Role> Roles { get; set; }
[Required]
[DisplayName("Topdesk Username")]
public string TDUserName { get; set; }
public virtual ICollection<TDOperator> Coaches { get; set; }
public List<string> CoachNames
{
get
{
return Coaches.Select(x => x.ToString()).ToList();
}
}
public virtual ICollection<TDOperator> Pupils { get; set; }
public List<string> PupilNames
{
get
{
return Pupils.Select(x => x.ToString()).ToList();
}
}
public override string ToString()
{
return this.FirstName + " " + this.LastName;
}
}
And the one for Role
public class Role
{
public int RoleID { get; set; }
public string Name { get; set; }
public int Priority { get; set; }
}
Sorry for messy code I intent to clean that up later.
When i run this it Generated a database with 3 Tables with columns:
- TDOperatorTDOperators
1.TDOperator_TDOperatorId
2.TDOperator_TDOperatorId1
- TDOperators
1.TDOperatorId
2.FirstName
3.LastName
4.EmailAdress
5.UserName
6.PassWord
7.LastLogin
8.TDUsername
- Roles
1.RoleId
2.Name
3.Priority
4.TDOperator_TDOperatorId <<--- WTF!
The problem with this is that i can now only assign a role To 1 user. There can only be 1 admin and 1 user for example. It is supposed to create and extra Foreign Key table but it doesnt!
Please help out.

You are not telling Entity Framework that you want the Roles -> Operators relationship. Try adding this to your Role class.
public virtual ICollection<TDOperator> Operators { get; set; }

Related

Entity Framework 6 Multiplicity is not valid?

I have two tables where I want to implement a 1-1 relationship.I run into a issue described in this post:
EntityFramework : Invalid column name *_ID1
I tried to implement the solution,to add the Foreign Key attribute and I run into another issue:
Multiplicity is not valid in Role 'Account_Companies_Target' in relationship 'Account_Companies'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.
These are the classes:
public class Account
{
[Key]
public Guid Id { get; set; }
public string CompanyName { get; set; }
public long CNP { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public long PhoneNumber { get; set; }
public string Address { get; set; }
[Required]
public string UserName { get; set; }
[Required(ErrorMessage = "Password is Required.")]
public string Password { get; set; }
public DateTime CreatedOn { get; set; }
[NotMapped]
[Required(ErrorMessage = "Confirmation Password is Required")]
[Compare("Password", ErrorMessage = "Password Must Match")]
public string ConfirmPassword { get; set; }
[Required]
public AccountType AccountType { get; set; }
public int CUI { get; set; }
[ForeignKey("Id")]
public virtual Company Companies { get; set; }
}
public class Company
{
[Key]
public long CUI { get; set; }
public Guid Id { get; set; }
public string CompanyName { get; set; }
public string Simbol { get; set; }
public int SharesCount { get; set; }
public decimal SharePrice { get; set; }
public virtual Account Account { get; set; }
}
and this is the OnModelCreating overide:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Account>()
.HasOptional(account => account.Companies)
.WithRequired(company => company.Account);
}
If Account.CUI, the foreign key property, is not a key, then the relationship is 1:many, not 1:1. And EF6 only allows an entity to have one key.

Why entity framework is referencing a column that doesn't even exist?

My project is throwing error
Invalid column name 'InitialsID_InitialsID'.
public User ValidateUser(string Username, string Password)
{
return uow.UserRepository.GetQueryable().Where(x => x.UserName == Username && x.Password == Password).FirstOrDefault();
}
Even there's no column by that name in the whole solution.
I had generated a migration script and it had that name in it but I changed that to InitialsID but still it asks for the same name.
How do I resolve it? I tried putting ForeignKey attribute etc but nothing works.
User.cs
public class User
{
public int UserID { get; set; }
public int UserGroupID { get; set; }
public UserGroup UserGroup { get; set; }
public string UserName { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
public string Designation { get; set; }
public string Password { get; set; }
public bool? PasswordExpire { get; set; }
public DateTime? ExpiryDate { get; set; }
public bool Status { get; set; }
public DateTime? CreatedOn { get; set; }
public string CreatedBy { get; set; }
public DateTime? ModifiedOn { get; set; }
public string ModifiedBy { get; set; }
public string Office { get; set; }
public string Station { get; set; }
public Initials InitialsID { get; set; }
}
Initials.cs
public class Initials
{
public short InitialsID { get; set; }
public string Code { get; set; }
}
I am using Code First approach.
Problem is in your foreign key configuration. When you are referencing navigation property public Initials InitialsID { get; set; }, EF is adding an implicit foreign key for this navigation property and it is by convention navigationPropery_navigationPropertyPrimaryKey and hence it is InitialsID_InitialsID
If you really want public Initials Initials { get; set; } navigaation property in User model class then write your foreign key configuration as follows:
public class User
{
public int UserID { get; set; }
public int UserGroupID { get; set; }
......................
public short InitialsId { get; set; }
public Initials Initials { get; set; }
}
It seems your database not migrated with new model or new models property,
Pleas migrate your database.
If you are using dotnet core, in cmd on the project folder type:
dotnet ef migrations add [name]
and then:
dotnet ef databae update

C# Entity Framework 6 MySQL - Unknown column being referenced on insert ApplicationUser_Id

I am using Entity Framework 6 with MySQL. Here are 2 of my models:
public class AppSession
{
[Key]
public int Id { get; set; }
[MaxLength(36)]
public string SesId { get; set; }
[ForeignKey("User")]
public string UserId { get; set; }
public DateTime CreatedOn { get; set; }
public virtual ApplicationUser User { get; set; }
public virtual ICollection<AppSessionBreakdown> Breakdown { get; set; }
}
public class AppSessionBreakdown
{
[Key]
public int Id { get; set; }
[ForeignKey("AppSession")]
public int ASId { get; set; }
public string FileName { get; set; }
public virtual AppSession AppSession { get; set; }
}
My C# code for inserting is:
var breakdown = new AppSessionBreakdown { ASId = snapSession.Id, FileName = fileName };
repositoryAppSessionsBreakdown.Insert(breakdown);
repositoryAppSessionsBreakdown.Save();
For some reasons, when I check the generated SQL, EF6 is adding an extra column which is not specified anywhere (ApplicationUser_Id) which insert statement is like this:
INSERT INTO `AppSessionBreakdowns`(`ASId`, FileName`, `ApplicationUser_Id`) VALUES (1, #gp1, NULL);
If I add an ApplicationUser column to the AppSessionBreakdown model, it does work but what can I do to prevent this as I don't want to add a useless column to make this just work.
ApplicationUser model:
public class ApplicationUser : IdentityUser
{
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Display(Name = "Surname")]
public string LastName { get; set; }
public bool Activated { get; set; }
[DisplayFormat(DataFormatString = "({0:dd MMM yyyy})")]
[Display(Name = "Activated On")]
public DateTime? ActivatedOn { get; set; }
[DisplayFormat(DataFormatString = "({0:dd MMM yyyy})")]
[Display(Name = "Last Logged In")]
public DateTime? LastLoggedIn { get; set; }
public int ContractorId { get; set; }
public bool TestAccount { get; set; }
public virtual ICollection<TapInSite> TapInSite { get; set; }
public virtual ICollection<TapInLog> TapInLog { get; set; }
public virtual ICollection<AppSession> SnapAppSessions { get; set; }
public virtual ICollection<AppSessionBreakdown> SnapAppSessionsBreakdown { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// 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;
}
}
You have a relation between ApplicationUser and AppSessionBreakdown that is in a type of one-to-many, for example:
And result of that will be:
For more information read Entity Framework Relationships and Navigation Properties.
Was including the column in the ApplicationUser class which caused this as mentioned in comments.

How to gain access to table data through foreign key reference?

I have a statement in one of my entities which uses a foreign key to return an IEnumerable<CustomField>.
I have used LINQ in my repository to test the below method to see if it works and it does. But when I use the foreign key reference in the entity it returns null. Am I missing something here? How can I use a foreign key to gain access to the data in another entity.
Invoice entity:
[Table("vwinvoice")]
public class Invoice
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int Sys_InvoiceID { get; set; }
[DisplayName("Inc.In Turnover")]
public bool Turnover { get; set; }
public int FK_StatusID { get; set; }
[DisplayName("Invoice No.")]
public string InvoiceNumber { get; set; }
[DisplayName("Invoice Date")]
public DateTime InvoiceDate { get; set; }
[DisplayName("Document Type")]
public string DocType { get; set; }
[DisplayName("Supplier Invoice No.")]
[Column("SupplierInvoiceNumber")]
public string SuppInvNumber { get; set; }
public int FK_SupplierID { get; set; }
[DisplayName("Account Number")]
public string AccountNumber { get; set; }
[DisplayName("Order Number")]
public string OrderNumber { get; set; }
[DisplayName("Order Date")]
public DateTime? OrderDate { get; set; }
[DisplayName("Currency Code_Doc")]
public string CurrencyCode_Doc { get; set; }
[DisplayName("Net Amount_Doc")]
public decimal? NetAmount_Doc { get; set; }
[DisplayName("VAT Amount_Doc")]
public decimal? VATAmount_Doc { get; set; }
[DisplayName("Gross Amount_Doc")]
[Required]
public decimal? GrossAmount_Doc { get; set; }
[DisplayName("Currency Code_Home")]
public string CurrencyCode_Home { get; set; }
[DisplayName("Net Amount_Home")]
public decimal? NetAmount_Home { get; set; }
[DisplayName("VAT Amount_Home")]
public decimal? VATAmount_Home { get; set; }
[DisplayName("Gross Amount_Home")]
public decimal? GrossAmount_Home { get; set; }
[DisplayName("Payment Reference")]
public string PaymentReference { get; set; }
[DisplayName("Supplier")]
public string AccountName { get; set; }
[DisplayName("Status")]
public string StatusName { get; set; }
[DisplayName("Auditor Comments")]
public string AuditorComments { get; set; }
[DisplayName("Reviewer Comments")]
public string ReviewerComments { get; set; }
[DisplayName("Data Source")]
[Required]
public string DataOrigin { get; set; }
public int DetailLineCount { get; set; }
public IEnumerable<CustomField> ClientData {
get {
//Use the CustomFields foreign key to gain access to the data returns null.
return GetCustomFieldData(this.CustomFields.Select(r => r));
}
}
private IEnumerable<CustomField> GetCustomFieldData(IEnumerable<Entities.CustomFields> enumerable) {
return (from f in enumerable
select new CustomField {
Name = f.FK_CustomHeader,
Value = f.Value
});
}
//Custom Field Additions
public virtual ICollection<CustomFields> CustomFields { get; set; }
}
CustomFields entity:
[Table("tblCustomFields")]
public class CustomFields
{
[Key]
public int ID { get; set; }
public int? FK_SysInvoiceID { get; set; }
[StringLength(255)]
public string FK_CustomHeader { get; set; }
[StringLength(255)]
public string Value { get; set; }
public virtual Invoice Invoices { get; set; }
public virtual CustomFieldHeaders CustomFieldHeaders { get; set; }
}
I also cannot place a breakpoint in the get statement to see what happens, why is this? It just skips over the breakpoint whenever I try to return a list of Invoices, which can be seen here:
public IQueryable<Invoice> Invoices
{
get
{
var x = _ctx.Invoices.ToList();
return _ctx.Invoices;
}
}
You are using the virtual keyword when declaring your CustomFields property. As such it will be lazy loaded. If you want the property to be populated once returned from the repository you will need to explicitly Include the table in your method:
var x = _ctx.Invoices.Include(i => i.CustomFields).ToList();
return _ctx.Invoices;
Or you can remove the virtual keyword and the property will always be populated, with the consequent performance hit of the database join and the extra data being returned whenever you access Invoices.

Complex relationship mappings in entity framework

I am building a reservation system. I have users in roles('admin', 'client', 'employee', 'student').
Each reservation must be associated with a user of role client, it might be assigned to user of role employee and might also be assigned to user of role student.
So in my reservation class I have properties of type User and I have marked them with [ForeignKey("AnytypeId")] attribute to hint EF for relations.
I have seen code like this at http://blog.stevensanderson.com/2011/01/28/mvcscaffolding-one-to-many-relationships/
public class Reservation
{
public int ReservationID
{
get;
set;
}
[Required(ErrorMessage="Please provide a valid date")]
public DateTime ReservationDate
{
get;
set;
}
public DateTime ReservationEnd { get; set; }
public DateTime EntryDate
{
get;
set;
}
public DateTime UpdatedOn
{
get;
set;
}
public decimal Ammount
{
get;
set;
}
public decimal? Discount { get; set; }
[DataType(DataType.MultilineText)]
public string ServiceDetails { get; set; }
[DataType(DataType.MultilineText)]
public string Remarks { get; set; }
public string VoucherNumber { get; set; }
public int ServiceID
{
get;
set;
}
public Service Service
{
get;
set;
}
public string EmployeeId { get; set; }
[ForeignKey("EmployeeId")]
public User Employee { get; set; }
public string ClientId { get; set; }
[ForeignKey("ClientId")]
public User Client { get; set; }
public string StudentId { get; set; }
[ForeignKey("StudentId")]
public User Student { get; set; }
}
public class User
{
//[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
//public Guid UserId { get; set; }
[Key]
[Required(ErrorMessage = "User Name is required")]
[Display(Name = "User Name")]
[MaxLength(100)]
public string UserName { get; set; }
[Required]
[MaxLength(64)]
public byte[] PasswordHash { get; set; }
[Required]
[MaxLength(128)]
public byte[] PasswordSalt { get; set; }
[Required(ErrorMessage = "Email is required")]
[DataType(DataType.EmailAddress)]
[MaxLength(200)]
public string Email { get; set; }
[MaxLength(200)]
public string Comment { get; set; }
[Display(Name = "Approved?")]
public bool IsApproved { get; set; }
[Display(Name = "Crate Date")]
public DateTime DateCreated { get; set; }
[Display(Name = "Last Login Date")]
public DateTime? DateLastLogin { get; set; }
[Display(Name = "Last Activity Date")]
public DateTime? DateLastActivity { get; set; }
[Display(Name = "Last Password Change Date")]
public DateTime DateLastPasswordChange { get; set; }
public string address { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string Phone { get; set; }
public bool? IsActive { get; set; }
public int? ClientTypeID { get; set; }
public virtual ClientType ClientType { get; set; }
public virtual ICollection<Role> Roles { get; set; }
public DateTime? PackageValidity { get; set; }
public virtual ICollection<Reservation> Reservations { get; set; }
}
public class UserMap : EntityTypeConfiguration<User>
{
public UserMap()
{
this.HasMany(u => u.Roles)
.WithMany(r => r.Users)
.Map(m =>
{
m.ToTable("RoleMemberships");
m.MapLeftKey("Username");
m.MapRightKey("RoleName");
});
}
}
Now as I run my mvc3 EF code first app database created for me on the fly with following ERD and edmx model.
Now few problems that I am having:
1. When I am listing all the users of role clients their reservation property is showing always 0 even if their are reservations available in database.
2. If I am trying to delete a user of role client who have reservation in database I get following error.
The DELETE statement conflicted with the REFERENCE constraint "Reservation_Client". The conflict occurred in database "CRSDB", table "dbo.Reservations", column 'ClientId'.
The statement has been terminated.
I checked the realtions in ERD and edmx model their is no cascade delete applied to them. How can I instruct EF to delete all the reservations when deleting user of role client but not for users of role employee or student.
This code does the trick
public class Reservation
{
public int ReservationID
{
get;
set;
}
[Required(ErrorMessage="Please provide a valid date")]
public DateTime ReservationDate
{
get;
set;
}
public DateTime ReservationEnd { get; set; }
public DateTime EntryDate
{
get;
set;
}
public DateTime UpdatedOn
{
get;
set;
}
public decimal Ammount
{
get;
set;
}
public decimal? Discount { get; set; }
[DataType(DataType.MultilineText)]
public string ServiceDetails { get; set; }
[DataType(DataType.MultilineText)]
public string Remarks { get; set; }
public String PaymentMethod { get; set; }
public string VoucherNumber { get; set; }
public int ServiceID
{
get;
set;
}
public virtual Service Service
{
get;
set;
}
public string EmployeeID { get; set; }
[ForeignKey("EmployeeID")]
public virtual User Employee { get; set; }
public string ClientID { get; set; }
[ForeignKey("ClientID")]
public virtual User Client { get; set; }
public string StudentID { get; set; }
[ForeignKey("StudentID")]
public virtual User Student { get; set; }
}
public class ReservationMap : EntityTypeConfiguration<Reservation>
{
public ReservationMap()
{
this.HasOptional(r => r.Client).WithMany().WillCascadeOnDelete(true);
this.HasOptional(r => r.Employee).WithMany().WillCascadeOnDelete(false);
this.HasOptional(r=>r.Student).WithMany().WillCascadeOnDelete(false);
}
}

Categories

Resources