我的模型中定义了多对一关系: Project.CreatedBy = ApplicationUser.Id:
class Project{
[Required]
public ApplicationUser CreatedBy {get; set;}
}
使用映射:
modelBuilder.Entity<Project>().HasOptional(i => i.CreatedBy).WithOptionalDependent().WillCascadeOnDelete(false);
不幸的是,当我尝试通过以下方式从DbContext检索所有用户时:
var users = context.Users;
生成的SQL看起来像:
SELECT
[...]
FROM [dbo].[AspNetUsers] AS [Extent1]
LEFT OUTER JOIN [dbo].[Projects] AS [Extent4] ON ([Extent4].[CreatedBy_Id] IS NOT NULL) AND ([Extent1].[Id] = [Extent4].[CreatedBy_Id])
因此,当某个用户创建了10个项目时,用户实体将乘以10次。这使我无法通过用户名查找该用户:
context.Users.Single(u => u.Username == "test")
因为它会给我序列包含多个元素异常。
您是否知道如何避免额外加入?
我怀疑它与modelBuilder声明有关。我一直在谷歌搜索,但从未找到任何解决方案。
关于modelBuilder的任何材料以及与它的定义关系都会非常感激。
答案 0 :(得分:0)
使用
.FirstOrDefault()
而非单身。
此方法将返回第一个对象,如果未找到对象,则返回null。如果选择了多个元素,则单个方法抛出异常。
您也可以使用
.First()
但是如果没有找到元素,这个方法将抛出异常。
PS我不确定这是不是一个错字,但你必须使用双等号,就像那样:
context.Users.Single(u => u.Username == "test")
请记住,通常在这些情况下,会创建LoweredUsername列并将其用于比较:
context.Users.Single(u => u.LoweredUsername == providedUsername.ToLower())
原因:
答案 1 :(得分:0)
我想在ApplicationUser中你有
public virtual ICollection<Project> Projects { get; set; }
请参阅MSDN中的turn off lazy loading for all entities
或者turning off lazy loading for specific navigation properties使Projects属性非虚拟
答案 2 :(得分:0)
映射......
modelBuilder.Entity<Project>()
.HasOptional(i => i.CreatedBy)
.WithOptionalDependent()
...将此表示为1:1关联,而不是您想要的1:n关联。
所以将映射更改为一对多:
modelBuilder.Entity<Project>()
.HasOptional(p => p.CreatedBy)
.WithMany()
.HasForeignKey(p => p.CreatedBy_Id);
我不确定为什么EF在查询Project
时加入User
,因为关联是可选的),但是正确的1:n映射会阻止它。