EF6没有按预期生成表连接

时间:2016-10-26 17:45:21

标签: join entity-framework-6

我有一个抽象的Entity类,我的所有实体都是从这个类派生出来的。此基类具有CreatedByModifiedBy属性,均为AppUser类型。由于AppUser也继承自Entity,我想知道这种循环是否令EF感到困惑。这是我的班级定义:

public abstract class Entity
{
    [Index(IsUnique = true)]
    public int Id { get; set; }
    [Required]
    public DateTime CreatedOn { get; set; }
    [Required]
    public DateTime ModifiedOn { get; set; }
    public AppUser CreatedBy { get; set; }
    public AppUser ModifiedBy { get; set; }
}

当我致电context.Users.ToArray()时,它会返回:

IsActive Identifier FirstName LastName MiddleName Id 
False    ee224559   bob       jones               1  
False    ee224559   bob       jones               1  
False    ee224559   bob       jones               1  
False    ee224559   bob       jones               1  
False    dheyue3    mary      smith    sue        21 
False    dheyue3    sarah     jones               22 

这是它生成的SQL:

SELECT 
"Extent1"."FIRSTNAME" AS "FIRSTNAME",
"Extent2"."FIRSTNAME" AS "CREATEDBY",
"Extent3"."FIRSTNAME" AS "MODIFIEDBY"
FROM   "MYSCHEMA"."APPUSER" "Extent1"
LEFT OUTER JOIN "MYSCHEMA"."APPUSER" "Extent2" ON 
("Extent2"."CREATEDBY_ID" IS NOT NULL) AND ("Extent1"."ID" = "Extent2"."CREATEDBY_ID")
LEFT OUTER JOIN "MYSCHEMA"."APPUSER" "Extent3" ON 
("Extent3"."MODIFIEDBY_ID" IS NOT NULL) AND ("Extent1"."ID" = "Extent3"."MODIFIEDBY_ID");

这就是我想要它生成的内容:

SELECT 
"Extent1"."FIRSTNAME" AS "FIRSTNAME",
"Extent2"."FIRSTNAME" AS "CREATEDBY",
"Extent3"."FIRSTNAME" AS "MODIFIEDBY"
FROM   "MYSCHEMA"."APPUSER" "Extent1"
LEFT OUTER JOIN "MYSCHEMA"."APPUSER" "Extent2" ON 
("Extent1"."CREATEDBY_ID" IS NOT NULL) AND ("Extent2"."ID" = "Extent1"."CREATEDBY_ID")
LEFT OUTER JOIN "MYSCHEMA"."APPUSER" "Extent3" ON 
("Extent1"."MODIFIEDBY_ID" IS NOT NULL) AND ("Extent3"."ID" = "Extent1"."MODIFIEDBY_ID");

我无法在代码块中加粗文本,因此请注意Extent限定符在连接中的交换方式。如何在第二个SQL示例中生成它们?

更新

这是我最初在OnModelCreating方法中使用的代码:

modelBuilder.Entity<AppUser>().HasOptional(x => x.CreatedBy).WithOptionalDependent();
modelBuilder.Entity<AppUser>().HasOptional(x => x.ModifiedBy).WithOptionalDependent();

根据回答者的推荐将其更改为:

modelBuilder.Entity<AppUser>().HasOptional(x => x.CreatedBy).WithMany();
modelBuilder.Entity<AppUser>().HasOptional(x => x.ModifiedBy).WithMany();

1 个答案:

答案 0 :(得分:1)

模型配置有些问题。

我创建了以下课程:

public class AppUser : Entity
{
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public string Identifier { get; set; }
    public bool IsActive { get; set; }
}

将其添加到我的测试DbContext(最新的EF6.1.3):

public DbSet<AppUser> AppUsers { get; set; }

并且没有任何其他配置出现异常

  

无法确定类型&#39; EFTest.AppUser&#39;之间关联的主要结尾。和&#39; EFTest.AppUser&#39;。必须使用关系流畅API或数据注释显式配置此关联的主要结尾。

所以我在OnModelCreating覆盖中添加了以下内容:

modelBuilder.Entity<AppUser>()
    .HasOptional(e => e.CreatedBy).WithMany();
modelBuilder.Entity<AppUser>()
    .HasOptional(e => e.ModifiedBy).WithMany();

现在迁移成功了。有趣的是,我已经创建了另一个Entity派生实体,并且它不需要这样的配置 - EF正确地确定与上面的配置相同,所以问题似乎是自我引用。

最后,执行以下LINQ查询:

var query = db.AppUsers
    .Select(u => new {  u.FirstName, CreatedBy = u.CreatedBy.FirstName, ModifiedBy = u.ModifiedBy.FirstName })
    .ToList();

按预期生成SQL:

SELECT 
    1 AS [C1], 
    [Extent1].[FirstName] AS [FirstName], 
    [Extent2].[FirstName] AS [FirstName1], 
    [Extent3].[FirstName] AS [FirstName2]
    FROM   [dbo].[AppUsers] AS [Extent1]
    LEFT OUTER JOIN [dbo].[AppUsers] AS [Extent2] ON [Extent1].[CreatedBy_Id] = [Extent2].[Id]
    LEFT OUTER JOIN [dbo].[AppUsers] AS [Extent3] ON [Extent1].[ModifiedBy_Id] = [Extent3].[Id]

很快,请检查您的配置和/或EF版本。