实体框架6 1对1关系映射不起作用

本文关键字:映射 不起作用 关系 实体 框架 | 更新日期: 2023-09-27 17:58:23

我正在将Entity Framework 6与现有数据库一起使用,并已从旧的自定义身份验证系统迁移了一些数据。

我有两个模型,一个扩展了MVC5中的脚手架ApplicationUser(Identity),另一个是旧表的模型。这些表具有1比1的关系。

因为我的身份验证表的UserId曾经是int,而ASP.NET Identity 2将ID定义为guid,所以我使用旧的UserId(它是tbl0102User的主键)创建了关联。

所以表格是:

AspNetUsers:
- Id (guid)
- Username etc
- UserId (int) - this is the column I have created on the table to map to the old User table
Tbl01012Users:
 - UserId (int)
 - address etc...

我对这两种型号的代码是:

 public class ApplicationUser : IdentityUser
    {
        public int UserId { get; set; }
        [ForeignKey("UserId")]
        public UserDetails Details { get; set; }
    }

[Table("tbl0102User")]
public class UserDetails
{
    // This numeric id contains the relationship between the old authentication system and the new ASP.NET Identity.
    // The new system has a Guid as Id, but that is different to the UserId.
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public ApplicationUser AppUser { get; set; }
    public string UserLogin { get { return AppUser.UserName; } }
    // etc....
}

当我尝试构建和运行应用程序时,我会得到以下错误:

System.InvalidOperationException: Unable to determine the principal end of an association between the types 'Plus.Models.ApplicationUser' and 'Plus.Models.UserDetails'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
   at System.Data.Entity.ModelConfiguration.Edm.Services.AssociationTypeMappingGenerator.GenerateIndependentAssociationType(AssociationType associationType, DbDatabaseMapping databaseMapping)
   at System.Data.Entity.ModelConfiguration.Edm.Services.DatabaseMappingGenerator.GenerateAssociationTypes(DbDatabaseMapping databaseMapping)
   at System.Data.Entity.ModelConfiguration.Edm.Services.DatabaseMappingGenerator.Generate(EdmModel conceptualModel)
   at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
   at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
   at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
   at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
   at System.Data.Entity.Internal.LazyInternalContext.get_CodeFirstModel()
   at System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(DbContext context, XmlWriter writer)
   at System.Data.Entity.Utilities.DbContextExtensions.<>c__DisplayClass1.<GetModel>b__0(XmlWriter w)
   at System.Data.Entity.Utilities.DbContextExtensions.GetModel(Action`1 writeXml)
   at System.Data.Entity.Utilities.DbContextExtensions.GetModel(DbContext context)
   at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext)
   at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration)
   at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.GetMigrator()
   at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force)
   at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0()
   at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)

为什么会这样?我已经在ApplicationUser对象上指定了Details属性的外键根据UserDetails对象上的外键userId进行映射。

我如何将其更改为工作?

我也尝试过流畅的映射,根据:http://msdn.microsoft.com/en-au/data/jj713564.aspx.

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<UserDetails>()
                .HasOptional(t => t.AppUser)
                .WithRequired(t => t.Details)
                ;            
        }

但是得到错误:

UserDetails_AppUser_Target: : Multiplicity is not valid in Role 'UserDetails_AppUser_Target' in relationship 'UserDetails_AppUser'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.

我也试过:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<UserDetails>()
                .HasRequired(x=>x.AppUser)
                .WithRequiredDependent(y=>y.Details)               
                ;            
        }

但是,我得到了错误:

UserDetails_AppUser_Target_UserDetails_AppUser_Source: : The types of all properties in the Dependent Role of a referential constraint must be the same as the corresponding property types in the Principal Role. The type of property 'UserId' on entity 'UserDetails' does not match the type of property 'Id' on entity 'ApplicationUser' in the referential constraint 'UserDetails_AppUser'.

对我来说,这表明它没有正确地在ApplicationUser上提取外键,而是使用主键ID(guid)。

实体框架6 1对1关系映射不起作用

我找到了答案:

public class ApplicationUser : IdentityUser
{
    public int UserId { get; set; }
    [ForeignKey("UserId")]
    public virtual UserDetails Details { get; set; }
}

我不确定这与我原来的有什么不同,只是我将UserDetails对象标记为虚拟对象。

您可以尝试指定如下外键:

public class ApplicationUser : IdentityUser
{
    [ForeignKey("UserDetails")]
    public int UserId { get; set; }
    public UserDetails Details { get; set; }
}

另一个选项可能是在UserDetails中的ApplicationUser属性上使用Required属性。