我有一个抽象的Entity
类,我的所有实体都是从这个类派生出来的。此基类具有CreatedBy
和ModifiedBy
属性,均为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();
答案 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版本。