我有以下实体:
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,但后来我收到此消息的异常:"无法确定相关操作的有效排序"
答案 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。最后请注意,如果可能,请分享两者的映射类。