使用ApplicationUser插入依赖实体

时间:2015-08-29 00:10:58

标签: c# entity-framework asp.net-web-api asp.net-identity asp.net-identity-2

我有以下实体:

public class ApplicationUser : IdentityUser
{
    ...
    public int? StudentId { get; set; }
    public virtual Student Student { get; set; }
}

public class Student
{
    public int Id { get; set; }
    public string UserId { get; set; }
    public virtual ApplicationUser User { get; set; }
}

我正在尝试创建一个新的应用程序用户和学生,所以我这样做:

var user = new ApplicationUser() {
    Name = "test",
    UserName = "test",
    Student = new Student ()
};

var result = await userManager.CreateAsync(user, "test12345!");

结果成功,两个实体插入数据库,但Student.UserId为空

如何插入实体及其关系?

我尝试设置student.UserId = user.Id,但后来我收到此消息的异常:"无法确定相关操作的有效排序"

2 个答案:

答案 0 :(得分:9)

此处One-to-one relationsip with optional dependent end using default conventions和此处EF Code First - 1-to-1 Optional Relationship提供了问题和解决方案。但是,让我在这个问题上添加一些内容。

您的实体设计在ApplicationUser相关的db表中创建冗余,但更重要的是,它会在两个表之间创建外键关系循环。虽然技术上可以处理这种关系,但这是一个维护的噩梦,应该避免。

EF代码第一种方法的优点是你不必考虑这些事情。不要尝试像db表那样设计POCO。除主键外,请勿使用xxxId属性。使用正确配置的导航属性来表示实体之间的关系,让EF处理数据库设计。

考虑到所有这些:

首先,从StudentId类中删除ApplicationUser属性,从UserId类中删除Student属性。请注意,这将从相应的db表中删除StudentId列,因此您可以考虑从新的db开始或使用迁移。

然后使用以下配置:

modelBuilder.Entity<ApplicationUser>()
    .HasOptional(u => u.Student)
    .WithRequired(s => s.User).Map(a => a.MapKey("UserId"));

你的问题应该解决了。

答案 1 :(得分:3)

您正在寻找学生和应用程序用户之间的一对一(零或一种)关系。因此,对于一个用户,可能有也可能不是学生。

在这种情况下,您不需要学生班中的应用程序用户ID,或者如果您需要,那么这将是您的基类。

<DataTemplate x:Key="platform_resources">
   <StackPanel Orientation="Horizontal">
      <Viewbox Width="30" Height="30" ToolTip="Network Domain Count" Stretch="Uniform">
           <ContentControl  DataContext="{Binding}" Focusable="False" Content="{DynamicResource appbar_server}" />
                </Viewbox>
                <TextBlock Margin="0,7,0,0" Text="{Binding Path=workload_count}"/>
                <Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
                <Viewbox Width="30" Height="30" ToolTip="Logical Network Count" Stretch="Uniform">
                    <ContentControl Focusable="False" Content="{DynamicResource appbar_network_server_connecting}" />
                </Viewbox>
                <TextBlock Margin="0,7,0,0" Text="{Binding Path=vlan_count}"/>
                <Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
                <Viewbox Width="30" Height="30" ToolTip="Network Domain Count" Stretch="Uniform">
           <ContentControl Focusable="False" Content="{DynamicResource appbar_network}" />
      </Viewbox>

     <TextBlock Margin="0,7,0,0" Text="{Binding Path=networkdomain_count}"/>

   </StackPanel>
</DataTemplate>

相反,如果你正在寻找一对一的关系

modelBuilder.Entity<ApplicationUser>() 
.HasKey(t => t.StudentId); 


// Map one-to-zero or one relationship 
modelBuilder.Entity<ApplicationUser>() 
    .HasRequired(t => t.Student) 
    .WithOptional(t => t.ApplicationUser);

在这两种情况下,您可能不需要同时使用Id。最后请注意,如果可能,请分享两者的映射类。