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

时间:2014-04-15 01:08:41

标签: c# ef-code-first asp.net-mvc-5 entity-framework-6

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

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

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

所以表格是:

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)。

2 个答案:

答案 0 :(得分:0)

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

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

    public UserDetails Details { get; set; }
}

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

答案 1 :(得分:0)

我找到了答案:

public class ApplicationUser : IdentityUser
{
    public int UserId { get; set; }

    [ForeignKey("UserId")]
    public virtual UserDetails Details { get; set; }
}

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