Collection of IdentyUsers in EntityFramework - has no key defined - entity-framework

All works well till i decide to add IdentityUser collection in another entity as navigation property.
One or more validation errors were detected during model generation:
IdentityUserLogin: : EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType.
IdentityUserRole: : EntityType 'IdentityUserRole' has no key defined. Define the key for this EntityType.
IdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins' is based on type 'IdentityUserLogin' that has no keys defined.
IdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles' is based on type 'IdentityUserRole' that has no keys defined.
But they are part of Microsoft.AspNet.Identity.EntityFramework library. How is it that they has no keys defined???
My entities and db context (EF v6.1, AspNet.Identity v.2.0):
public class User : IdentityUser
{
public virtual int OrganizationId { get; set; }
public virtual Organization Organization { get; set; }
}
public class Organization
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
}
public class DatabaseModelContext : IdentityDbContext<User>
{
public DatabaseModelContext() : base("ConnectionString") { }
public DbSet<Organization> Organizations { get; set; }
}
Also tried to define explicit relations:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Organization>()
.HasMany(o => o.Users)
.WithOptional(u => u.Organization)
.HasForeignKey(u => u.OrganizationId);
modelBuilder.Entity<User>()
.HasOptional(u => u.Organization)
.WithMany()
.HasForeignKey(u => u.OrganizationId);
}
NO success!!!
It cant just be, that one must define key types for entity framework internal classes!!!
SOLUTION (update)
Actually my simplified example not reflecting my real app situation. My apologies.
I've been using multiple Dbcontexts in my app and organization entity come from separate context what derives form Dbcontext class. In that way this context know nothing about IdentityUser models but Organization entity involves User entity - there is a problem.
Solution - i derived all my other context from IdentityDbContext !!!

Actually my simplified example not reflecting my real app situation. My apologies. I've been using multiple Dbcontexts in my app and organization entity come from separate context what derives form Dbcontext class. In that way this context know nothing about IdentityUser models but Organization entity involves User entity - there is a problem.
Solution - i derived all my other context from IdentityDbContext !!!

Related

EF Core: Change naming strategy of FK Shadow Properties?

In EF Core, when defining Relationships, one can either provide the necessary FK properties explicitly or not:
Explicit FK property:
public class Person
{
public Guid Id { get; set; }
public ICollection<ParentIdentity> Identities { get; set; }
...
}
public class PersonIdentity
{
public Guid Id { get; set; }
public PersonFK { get; set; } //Explicit Data storage FK field in System Logic Entity :-(
...
}
The relationship would be defined in Fluent API as follows:
model.HasMany(x => Identities) // Person can have multiple identities
.WithOne() // Identity does not need a Nav property back up to Person
.WithForeignKey(x => x.PersonFK) // Hardcoded the FK.
The upside is its eminently clarity of how it's hooked up.
The downside is the blurring of domains between system logic and storage -- in that the system entity now has Data storage specific attributes (PersonFK) that have nothing to do with system logic that developers should be concentrating on.
Shadow properties
The alternative is to let EF sort it out, using shadow properties, by not define an FK Property on the Entity:
public class Person
{
public Guid Id { get; set; }
public ICollection<ParentIdentity> Identities { get; set; }
...
}
public class PersonIdentity
{
public Guid Id { get; set; }
...
}
And define the relationship as follows:
model.HasMany(x => Identities) // Person can have multiple identities
.WithOne() // Identity does not need a Nav property back up to Person
//.WithForeignKey(x => x.PersonFK) // Don't provide an FK property
;
EF will step up and add a property to the db table named to the following convention:
<principal primary key property name>Id
//ie, will be created as `PersonId`
But let's say I want to change it to:
<principal primary key property name>FK
//ie, will be created as `PersonFK`
Question
How?
Foraging so far
In case it helps, I'm looking in the following direction:
I can see a SqlServerConventionSetBuilder that inherits from RelationalConventionSetBuilder that inherits from ProviderConventionSetBuilder.
ProviderConventionSetBuilder in turn calls
ForeignKeyIndexConvention
ForeignKeyPropertyDiscoveryConvention
ForeignKeyAttributeConvention
found some sparse documentation at https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.metadata.conventions.foreignkeyindexconvention?view=efcore-6.0
but not enough there to know where to look really.
Can someone point me in the right direction as to:
what convention to replace
how to replace it easily?
Thank you!

How can I implement a 1..n bi-directional relationship in Entity Framework Code First

I am absolutely stumped in trying to figure out how to implement a bi-directional 1..n relationship in Entity Framework using Code First. For example, a team (represented by a Team entity) has a coach and a manager (both represented by a Person entity). So, my Team model could be as follows:
public class Team
{
public Team()
{
Manager = new Person();
Coach = new Person();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TeamID { get; set; }
public string Name { get; set; }
[ForeignKey("Manager")]
public int ManagerID { get; set; }
public virtual Person Manager { get; set; }
[ForeignKey("Coach")]
public int CoachID { get; set; }
public virtual Person Coach { get; set; }
}
I can implement one-way navigation by implementing the Person Entity as follows:
public class Person
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int PersonID { get; set; }
public string Name { get; set; }
}
and the fluent API:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Team>()
.HasRequired(t => t.Manager);
modelBuilder.Entity<Team>()
.HasRequired(t => t.Coach);
base.OnModelCreating(modelBuilder);
}
However, while that allows me to navigate from the Team entity to the related Coach and Manager (both instances of Person), it doesn't allow me to directly navigate from the Coach or Manager to the related Team. So, to implement 2-way navigation, I modified the Person entity as follows:
public class Person
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int PersonID { get; set; }
public string Name { get; set; }
[ForeignKey("Team")]
public int TeamID { get; set; }
public virtual Team Team { get; set; }
}
While that builds ok, I get the following runtime error when I try to save to the database:
System.Data.Entity.Core.UpdateException
InnerException: Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values.
So, to specify the ordering between the entities, I tried to modify the fluent API by adding the "WithRequiredPricipal" as follows:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Team>()
.HasRequired(t => t.Manager)
.WithRequiredPrincipal(t => t.Team);
modelBuilder.Entity<Team>()
.HasRequired(t => t.Coach)
.WithRequiredPrincipal(t => t.Team);
base.OnModelCreating(modelBuilder);
}
However, when I attempt to execute "add-migration" in the Package Manager Console, I get the following error:
System.InvalidOperationException: The navigation property 'Team' declared on type 'RelatedEntities.Models.Person' has been configured with conflicting foreign keys.
What I'm attempting to achieve seems like a straightforward requirement but I've done heaps of searching for a solution without yet finding an answer. Am I missing something in the fluent API or the annotations?
(I don't want to implement a workaround, such as implementing separate models for Coach and Manager because a team may have numerous other roles (eg, Assistant Coach, Public Relations Manager, etc). I would want each to simply be an instance of a Person entity.)
You didn't define your foreign key constraints.
.HasRequired(t => t.Manager)
.WithMany()
.HasForeignKey(t => t.ManagerId)
As a side note. If your manager was managing multiple teams the WithMany would be .WithMany(m => m.Teams) and your manager model would need something like this:
private ICollection<Team> _teams
public ICollection<Team> Teams
{
get { return _teams ?? (teams = new List<Team>()); }
protected set { _teams = value; }
}
Sorry for formatting. On my phone. Good luck.
Ok, I can now answer my own question in case anyone else encounters the same problem.
Firstly, as I mention in my comment above, the problem that I described in my question turns out to be a recognized shortcoming in Entity Framework that the EF Triage Team has flagged to be addressed in a future release of EF.
In the meantime, the workaround that has been suggested by a number of contributors in response to questions about how to implement circular dependencies in EF (which is what my example above is trying to do) is to do it in stages as follows:
Create the principal entity
Call SaveChanges() on DbContext
Create the dependent entity and set the foreign key before calling SaveChanges() again (at some subsequent point)
So, using the Team example in my original question above, instead of creating the dependent Manager and Coach entities in the Team constructor, the first change was to make the Team's foreign keys to the Coach and Manager optional (instead of required), so that the Team could be instantiated without the Coach and Manager, and then call SaveChanges():
Team team = Teams.Add(new Team());
SaveChanges();
After that, I then create the dependent Manager and Coach entities and set their foreign keys to the ID of the Team instance:
team.Manager = new Person();
team.Manager.TeamID = team.TeamID;
team.Coach = new Person();
team.Coach.TeamID = team.TeamID;
At any time after that, SaveChanges() can be called without causing a runtime error as previously.
When this issue is addressed in a future release of EF, it should be possible to create the principal and dependent entities without having to call SaveChanges() in between.

Entity Framework 6.1 Unidirectional Navigation Property 0 to Many with Fluent API

I'm new to EF and am having issues trying to create a unidirectional navigation association (0 to many) using the Fluent API. Here are simplified versions of the classes:
public partial class Company
{
public int Id { get; set; }
// "Company" is NOT REQUIRED to have any BillingInfo records/objects
public virtual IList<BillingInfo> BillingInfos { get; set; }
}
public partial class BillingInfo
{
public int Id { get; set; }
// A "BillingInfo" requires ONE "Company"
public int Company_Id { get; set; }
}
I'm using EF 6.1 Code First with migrations enabled along with SQL Server 2012.
In my derived EntityTypeConfiguration classes for "Company" and "BillingInfo", I've tried every which way I can think of to achieve:
A Company DOES NOT REQUIRE any BillingInfo records, but MAY HAVE MANY.
A BillingInfo DOES REQUIRE only ONE Company.
Maintain a unidirectional navigation between Company and BillingInfo. (don't want to have a Company navigation property on BillingInfo)
EF Migration creates the NON-NULLABLE Company_Id field in database, WITH a defined ForeignKey constraint.
All the methods I've tried, only gets me partially there. The closest I've come is this (but the only thing missing is the foreignkey constraint isn't created):
class CompanyConfig : EntityTypeConfiguration<Company>
{
public CompanyConfig()
{
this.HasOptional(company => company.BillingInfos)
.WithMany()
.Map(m => m.MapKey("Company_Id"));
}
}
Any ideas???
I think you should use the following code:
private class CompanyMapping : EntityTypeConfiguration<Company>
{
public CompanyMapping()
{
this.HasMany(o => o.BillingInfos).WithOptional().HasForeignKey(fk => fk.Company_Id);
}
}
private class BillingInfoMapping : EntityTypeConfiguration<BillingInfo>
{
public BillingInfoMapping()
{
this.HasOptional(o => o.Company).WithMany(c=>c.BillingInfos).HasForeignKey(fk => fk.Company_Id);
}
}

Code first migration - sub-class requires Id field

I have a standard MVC 5 project in VS 2013 and using the built-in Identity provider. I am trying to customize the user profile according to http://blogs.msdn.com/b/webdev/archive/2013/10/16/customizing-profile-information-in-asp-net-identity-in-vs-2013-templates.aspx.
I did not expand on ApplicationUser as in the article as I wanted to work on the extension in another project in the same solution. I created a new sub-class ExtendedUser:
public class ExtendedUser : IdentityUser
{
[MaxLength(12)]
public string PIN { get; set; }
}
I then have:
public class UsersContext : DbContext
{
public DbSet<ExtendedUser> ExtendedUsers { get; set; }
public UsersContext() : base() { }
public UsersContext(string ConnectionString) : base(ConnectionString) { }
}
When UsersContext is instantiated and initialized, I get hit by:
System.Data.Entity.ModelConfiguration.ModelValidationException was unhandled by user code
HResult=-2146233088
Message=One or more validation errors were detected during model generation:
IdentityUserLogin: : EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType.
IdentityUserRole: : EntityType 'IdentityUserRole' has no key defined. Define the key for this EntityType.
IdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins' is based on type 'IdentityUserLogin' that has no keys defined.
IdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles' is based on type 'IdentityUserRole' that has no keys defined.
....
It seems like the other Identity membership tables are updated, but I did not touch any of those. Why is this happening and how do I correct it.
Try IdentityDbContext<ExtendedUser> as your base class for UsersContext as it is in the post you have mentioned. Without it you don't have any line of code to tell ef which property is the key. If you don't want IdentityDbContext you should in method void OnModelCreating(DbModelBuilder modelBuilder) put property mapping, something like:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ExtendedUser>().HasKey(t => t.Id);
...
}

Entity Framework Code First One-to-One Required-Required Relationship

When using Entity Framework Code First 4.3.1 it is possible to create relationships with a multiplicity of 1-to-1. That is, one entity on each end of the relationship.
It is possible to configure 1-to-1 relationships to be required-required or required-optional ^. However, when I switch between the two I do not see any differences in:
The database schema generated. I am targeting SQL Server 2008.
The runtime behaviour of EF.
As such, I am able to create a RequiredPrincipalAs record without a corresponding RequiredDependentAs record, despite the relationship being configured as required-required. This seems to contradict the documentation for HasRequired(...):
Configures a required relationship from this entity type. Instances of the entity type will not be able to be saved to the database unless this relationship is specified. The foreign key in the database will be non-nullable.
http://msdn.microsoft.com/en-us/library/gg671317
The required-required relationship entities:
public class RequiredPrincipalA
{
public int Id { get; set; }
public virtual RequiredDependentA DependentA { get; set; }
}
public class RequiredDependentA
{
public int Id { get; set; }
public virtual RequiredPrincipalA PrincipalA { get; set; }
}
The required-optional relationship entities:
public class RequiredPrincipalB
{
public int Id { get; set; }
public virtual OptionalDependentB DependentB { get; set; }
}
public class OptionalDependentB
{
public int Id { get; set; }
public virtual RequiredPrincipalB PrincipalB { get; set; }
}
The DbContext and model configuration:
public class AppContext : DbContext
{
public DbSet<RequiredPrincipalA> PrincipalAs { get; set; }
public DbSet<RequiredDependentA> DependentAs { get; set; }
public DbSet<RequiredPrincipalB> PrincipalBs { get; set; }
public DbSet<OptionalDependentB> DependentBs { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<RequiredPrincipalA>()
.HasRequired(o => o.DependentA)
.WithRequiredPrincipal(o => o.PrincipalA);
modelBuilder.Entity<RequiredPrincipalB>()
.HasOptional(o => o.DependentB)
.WithRequired(o => o.PrincipalB);
}
}
The test code:
Database.SetInitializer(new DropCreateDatabaseAlways<AppContext>());
using (var ctx = new AppContext())
{
ctx.Database.Initialize(force: false);
ctx.PrincipalAs.Add(new RequiredPrincipalA());
ctx.PrincipalBs.Add(new RequiredPrincipalB());
ctx.SaveChanges();
}
I am aware I could add a [Required] data attribute to the navigation properties of RequiredPrincipalA.DependentA and RequiredDependentA.PrincipalA. This would cause EF validation to prevent the scenario above. However, I do not want to do this because it also validates the navigation property is populated when updating an existing entity. This means the application has to pre-fetch the entity at the other end of the relationship for every update.
Why do I not see any difference in the behaviour of EF just when changing a relationship between required-required and required-optional?
^ Note that optional-optional is also supported but this doesn't form part of my question. There are obvious differences in the generated database schema and runtime behaviour when an optional-optional relationship is configured.
I don't know why required-required is allowed for this case but it cannot exist in the database because relation is build on primary keys. Required-required means that A cannot be inserted if related B doesn't exist and B cannot be inserted if related A doesn't exist => neither A or B can be inserted.
Database relation has always principal and dependent entity - principal can always exist without dependent.
Real required-required in EF can be achieved only when both A and B are mapped to the same table (table splitting) because in such case they are both inserted with single insert command.
Not really an answer but I have more to say than will fit in comments. But you know, I write 900 page books...it's just how I roll. :)
Oddly I would expect the fluent configuration to behave the same way as the data annotation and am confused that it's not doing it. (I've pinged Rowan Miller with a link to this thread to get his feedback.) And the behavior I mean is: validating the constraint during SaveChanges.
On the database side, I'm with Ladislav.In the model, EF defines the 1:1 using the keys of the related entities. But in the database, you can't have FKs in both tables, so only the dependent table in the database will require that constraint that it's PK maps to an existing PK in the principal table.
And finally, I understand your reason for not wanting EF to enforce the relationship if you aren't going to always deal with teh full graph. I think 1:1 relationships are the most confusing of the EF relationship mappings and I always find myself having to go back for reminders of the rules and how things should work.
Old question. But since EF6 is still used and even available for .Net standard and this issue can be a real nuisance, I think it's worth mentioning something I couldn't find in other answers.
It is true that both HasRequired - WithRequiredPrincipal and HasOptional - WithRequired produce the same database schema and the same runtime behavior. That is, with both mappings it's possible to save a principal without a dependent entity and to remove the dependent later. So much for HasRequired.
But there is a way to make EF validate the required relationship when creating the entities, which is by simply adding a [Required] attribute:
public class RequiredPrincipalA
{
public int Id { get; set; }
[Required] // <== here
public virtual RequiredDependentA DependentA { get; set; }
}
public class RequiredDependentA
{
public int Id { get; set; }
public virtual RequiredPrincipalA PrincipalA { get; set; }
}
As said, only when creating the entities. It's still possible to set RequiredPrincipalA.RequiredDependentA = null and save it successfully. But I think that, fortunately, the likelihood of that happening in code is far lower than forgetting to set the required dependent.