4

我有以下实体:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class HappyUser : User
{
    public bool IsHappy { get; set; }
}

我正在使用 Table Per Concrete Type (TPC) 配置实体,以生成 User 表和 HappyUser 表。我希望 HappyUser 表包含 User 类的属性,并且我不希望这两个表之间有任何关系。

我将实体配置如下:

public class UserTest : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<HappyUser> HappyUsers { get; set; }


    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<HappyUser>().Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("HappyUser");
        });
    }
}

表生成正确,但是当我查询表时,EF 在 User 和 HappyUser 表上生成一个 UNION。查询如下:

        UserTest db = new UserTest();

        var users = from u in db.Users
                    select u;

        var happyUsers = from u in db.Users.OfType<HappyUser>()
                         select u;

用户的 SQL 生成一个 UNION。这不是我所期望或想要的。我想简单地从用户表中检索行。

SELECT 
CASE WHEN ([UnionAll1].[C2] = 1) THEN '0X' ELSE '0X0X' END AS [C1], 
[UnionAll1].[Id] AS [C2], 
[UnionAll1].[Name] AS [C3], 
CASE WHEN ([UnionAll1].[C2] = 1) THEN CAST(NULL AS bit) ELSE [UnionAll1].[C1] END AS [C4]
FROM  (SELECT 
 [Extent1].[Id] AS [Id], 
 [Extent1].[Name] AS [Name], 
 CAST(NULL AS bit) AS [C1], 
 cast(1 as bit) AS [C2]
 FROM [dbo].[User] AS [Extent1]
UNION ALL
 SELECT 
 [Extent2].[Id] AS [Id], 
 [Extent2].[Name] AS [Name], 
 [Extent2].[IsHappy] AS [IsHappy], 
 cast(0 as bit) AS [C1]
 FROM [dbo].[HappyUser] AS [Extent2]) AS [UnionAll1]

HappyUsers 的 SQL 按预期工作。

SELECT 
'0X0X' AS [C1], 
[Extent1].[Id] AS [Id], 
[Extent1].[Name] AS [Name], 
[Extent1].[IsHappy] AS [IsHappy]
FROM [dbo].[HappyUser] AS [Extent1]

任何想法我做错了什么?或者这是 EF 的缺陷?

4

2 回答 2

1

HappyUsers用户。因此,db.Users 应该同时返回。EF是正确的,在这里。

但是,EF 确实有一个限制:没有办法(无论如何在 L2E 中)返回一种类型的结果。由于 Liskov Substitution Principal,您通常不希望这样做。但是如果你这样做了,你可以在 ESQL 中进行,并且有(有些乏味的)L2E 解决方法

底线:如果您发现自己想要这样做,请重新考虑您的设计。在这种情况下,继承可能不是正确的关系。

于 2011-01-27T20:44:13.970 回答
1

@Craig Stuntz 是对的,因为这两种类型都是相关的,EF 将保持这种关系不变。

如果您想解耦两种用户类型,那么您可以使用抽象基类。

public abstract class AbstractUser
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class User : AbstractUser
{
}

public class HappyUser : AbstractUser
{
    public bool IsHappy { get; set; }
}

EF 现在会将这两个实体视为独立的,不再需要调用MapInheritedProperties()

您的选择语句将如下所示:

var users = db.Users.Where(...);
var happyUsers = db.HappyUsers.Where(...);
于 2011-01-27T21:49:46.527 回答