I'm having problems trying to create relationships of 0..1 to 0..1 using code first between AspNetUsers table extending the applicationuser class and MyUserInfo class. The nature of the relationship is that a user can have one MyUserInfo or not.
My Models:
public class MyUserInfo
{
[Key]
public int MyUserInfoId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserId { get; set; }
[ForeignKey("UserId")]
public virtual ApplicationUser User { get; set; }
}
ApplicationUser class:
public class ApplicationUser : IdentityUser
{
public int? MyUserInfoId { get; set; }
[ForeignKey("MyUserInfoId")]
public virtual MyUserInfo MyUserInfo { 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;
}
Logically it should work. Got two foreign keys. One foreign key in ApplicationUser class (AspNetUser table) and one foreign key in MyUserInfo class.
Somehow I get this error on adding migration:
Unable to determine the principal end of an association between the
types 'IdentityDemoByThanh.Models.MyUserInfo' and
'IdentityDemoByThanh.Models.ApplicationUser'. The principal end of
this association must be explicitly configured using either the
relationship fluent API or data annotations.
Why do I get this kind of error?
Thanks in advance.
Related
I have three entities, User, Domain and Role.
I have this class to define the relationship of the three entities:
public class UserDomainRole
{
[Key]
public int UserId { get; set; }
[Key]
public int DomainId { get; set; }
[Key]
public int RoleId { get; set; }
}
So how to I setup a foreign key relationship between UserDomainRole and other three table?
Is it something like this?
public class DeniedDomainRole
{
[Key]
public int UserId { get; set; }
public virtual User User { get; set; }
[Key]
public int DomainId { get; set; }
public virtual Domain Domain { get; set; }
[Key]
public int RoleId { get; set; }
public virtual Role Role { get; set; }
}
Then entity framework will work the relationship out?
This code will give you an exception with a message "Unable to determine composite primary key ordering"
In code first if you want to create a composite primary key then you have to use the to give the key/column order, like that:
[Key, Column(Order=1)]
Where
Order = The composite Primary key/column order on the table
public class UserDomainRole
{
[Key, Column(Order=1)]
public int UserId { get; set; }
[Key, Column(Order=2)]
public int DomainId { get; set; }
[Key, Column(Order=3)]
public int RoleId { get; set; }
}
So how to I setup a foreign key relationship between UserDomainRole and other three table? Is it something like this?
It is depending on what kind of the relationships you have:
Configure One-to-Zero-or-One Relationship:
Here, we will configure One-to-Zero-or-One relationship between two entities, e.g. Entity1 can be associated with zero or only one instance of Entity2.
http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx
Configure One-to-Zero-or-One Relationship:
Here, we will configure One-to-Zero-or-One relationship between two entities, e.g. Entity1 can be associated with zero or only one instance of Entity2.
http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx
Configure Many-to-Many relationship:
Here, we will learn how to configure Many-to-Many relationship between the Student and Course entity classes. Student can join multiple courses and multiple students can join one course.
http://www.entityframeworktutorial.net/code-first/configure-many-to-many-relationship-in-code-first.aspx
In this way you can relation with the user model
public int? UserUserId{get;set;}
public virtual User User{get;set;}
? makes nullable your foreignkey.
I'm having problems trying to create relationships of 0..1 to 0..1
using code first between AspNetUsers table extending the applicationuser class and MovieModel.
The nature of the relationship is that a user can rent one movie or not and
a movie can be rented to one renter or not. Each entity can stand by itself
and when there is no movie rented or renter the foreign fields are just nulls
My models:
public class MovieModel
{
[Key]
public int MovieId { get; set; }
[Required]
[StringLength(50)]
[Column(TypeName="varchar")]
[Display(Name = "Movie Name")]
public string MovieName { get; set; }
[Display(Name = "Release Year")]
public string RenterId { get; set; }
[ForeignKey("RenterId")]
public virtual ApplicationUser Renter { get; set; }
ApplicationUser Class
public class ApplicationUser : IdentityUser
{
public int? MovieId { get; set; }
[ForeignKey("MovieId")]
public virtual MovieModel Movie{ 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;
}
}
Logically it should work. Got two foreign keys. One foreign key in ApplicationUser class (AspNetUser table) and one foreign key in MovieModel
Somehow I get this error on adding migration:Unable to determine the principal end of an association between the types 'VideoLibrary.Models.ApplicationUser' and 'VideoLibrary.Models.MovieModel'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotation
Why do I get this kind of error? I don't need a principal entity in the relationship. They both can stand alone.
Thanks in advance
EF Code First supports 1:1 and 1:0..1 relationships. Maybe you should try "one to zero-or-one".
I removed the data annotation and created it by the model builder.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<AllesVersUser>()
.HasOptional<MovieModel>(l => l.Movie)
.WithOptionalDependent(c => c.Renter)
.Map(p => p.MapKey("MovieId"));
base.OnModelCreating(modelBuilder);
}
Tried this in my solution, and I can have movies without a renter, and users without a movie.
I'm creating a simple application for university where a student can make some type of request which is then processed by an employee of particular speciality.
I would like to use default MVC5 identity system and to extend the ApplicationUser class using TPH pattern. So I added the common properties to the ApplicationUser:
public class ApplicationUser : IdentityUser
{
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string Email { get; set; }
}
then I created two classes which inherits the ApplicationUser:
public class Student : ApplicationUser
{
public string PersonalNumber { get; set; }
public bool Monitor { get; set; }
public virtual Group Group { get; set; }
public virtual ICollection<Request> Requests { get; set; }
}
public class Employee : ApplicationUser
{
public virtual EmployeeSpeciality EmployeeSpeciality { get; set; }
public virtual ICollection<Request> Requests { get; set; }
}
what I currently want is to make both types of users register as a base Identity and to keep both in a single table as in the inheritance example on asp.net
As I thought, it would be enough to initialize user var in AccountController which is then passes to the UserManager as a Student or as an Employee. But after trying to register as a Student i'm getting this exception:
Exception Details: System.Data.SqlClient.SqlException: Invalid column name 'PersonalNumber'.
Invalid column name 'Monitor'.
Invalid column name 'EmployeeSpeciality_Id'.
Invalid column name 'Group_Id'.
My context class:
public class EntityContext : IdentityDbContext
{
public EntityContext()
: base("DbConnection")
{
}
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public DbSet<Student> Students { get; set; }
public DbSet<Employee> Employees { get; set; }
...
}
and a part of controller's action:
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new Student()
{
UserName = model.UserName,
FirstName = model.FirstName,
LastName = model.LastName,
Email = model.Email
};
var result = await UserManager.CreateAsync(user, model.Password);
I tried setting ApplicationClass to an abstract class, but no luck. Any help would be appreciated.
UPDATE: The problem wasn't in the code itself. I simply haven't dropped (or updated) the database after making these changes to the model. After it everything works just fine.
#Dragonheart: I tried this repro and it would work fine if you remove the DBSet declarations in you context class. The IdentityDbContext would handle you TPH pattern and add a Discriminator column in the table to differentiate the child classes.
As ApplicationUser is inherited from IdentityUser, remove it from your DbContext class. On the other hand, there is no need to create an abstract class (you can create if you prevent from creating a user except from Student or Employee classes. For more information you might have a look at Table-per-Hierarchy.
For Register part, try something like that:
Student user = new Student
{
UserName = model.UserName,
FirstName = model.FirstName,
LastName = model.LastName,
Email = model.Email
};
var result = UserManager.Create(user, model.Password);
Hope this helps...
I have a problem with the Entity Framework.
public class User : Receiver
{
public User()
{
if (Groups == null)
Groups = new List<Group>();
if (Buddies == null)
Buddies = new List<User>();
}
[Required]
public string PhoneNumber { get; set; }
[ForeignKey("Guid"), JsonIgnore]
public IList<User> Buddies { get; set; }
[ForeignKey("Guid"), JsonIgnore]
public IList<Group> Groups { get; set; }
}
public class Receiver
{
public Receiver()
{
Guid = Guid.NewGuid();
Created = DateTime.Now;
}
[Key]
public Guid Guid { get; set; }
[Required]
public DateTime Created { get; set; }
}
When i try to add a user...
User user = new User
{
Guid = new Guid("8cd094c9-e4df-494e-b991-5cf5cc03d6e3"),
PhoneNumber = "+4991276460"
};
cmc.Receivers.Add(user);
... it ends in follogwing error.
The object of the Type "System.Collections.Generic.List`1[Project.Models.User]" can't be converted to "Project.Models.User".
When i comment out following two lines:
[ForeignKey("Guid"), JsonIgnore]
public IList<User> Buddies { get; set; }
...the programm runs fine.
I hope someone can help me to fix this problem.
Otherwise it runs into an error at this line : cmc.Receivers.Add(user);
In your mapping...
[ForeignKey("Guid"), JsonIgnore]
public IList<User> Buddies { get; set; }
...you specify that User.Buddies is part of a one-to-many relationship and that User.Guid (=Receiver.Guid) is the foreign key in this relationship. But User.Guid is also the primary key, hence it must be unique. As a result a User cannot have a list of Buddies but only a single reference.
The mapping makes no sense but the exception is not very helpful and difficult to understand. (Somehow EF seems to recognize internally that the Buddies cannot be a list with that mapping and wants to cast the list to a single reference. It should detect in my opinion that the mapping is invalid in the first place.)
For a correct one-to-many mapping you need a foreign key that is different from the primary key. You can achieve that by either removing the [ForeignKey] annotation altogether...
[JsonIgnore]
public IList<User> Buddies { get; set; }
...in which case EF will create a default foreign key in the Receivers table (it will be some column with an underscore in its name, but you can rename that with Fluent API if you don't like the default name) or by adding your own foreign key property to the User class:
public Guid? BuddyGuid { get; set; }
[ForeignKey("BuddyGuid"), JsonIgnore]
public IList<User> Buddies { get; set; }
I'm currently getting the following error when trying to create an one to one relationship using Code First:
System.Data.Edm.EdmAssociationEnd: : Multiplicity is not valid in Role 'C001_Holding_Teste_C001_Holding_Source' in relationship 'C001_Holding_Teste_C001_Holding'. Because the Dependent Role refers to the key properties, the upper bound of the multiplicity of the Dependent Role must be 1.
My entity definitions are the following:
[Table("C001_Holding", Schema = "Cad")]
public partial class C001_Holding
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int C001_Id { get; set; }
[MaxLength(16)]
public string C001_Codigo { get; set; }
[MaxLength(100)]
public string C001_Descricao { get; set; }
}
public class C001_Holding_Test
{
[Key]
public int C001_Id { get; set; }
[MaxLength(100)]
public string C001_TestInfo { get; set; }
[ForeignKey("C001_Id")]
public virtual C001_Holding C001_Holding { get; set; }
}
I didn't want to use Fluent to create these relationships, does anyone knows why this is happening?
Tks.
It is possible to place the ForeignKey attribute either on a navigation property and then specify the name of the property you want to have as the foreign key (that's what you did). Or you can place it on the foreign key property and then specify the name of the navigation property which represents the relationship. This would look like:
public class C001_Holding_Test
{
[Key]
[ForeignKey("C001_Holding")]
public int C001_Id { get; set; }
[MaxLength(100)]
public string C001_TestInfo { get; set; }
public virtual C001_Holding C001_Holding { get; set; }
}
For some reason this second option works while the first throws an error. (It feels like a bug to me because both options should represent the same relationship. Or there is actually a semantic difference which I don't see...)