EF代码中的一个实体多个表首先正确表名

时间:2014-10-06 07:30:32

标签: c# entity-framework

如何在EF中将多个数据库表映射到单个实体并获得正确的查询? 我有一个用户实体:

public class User
    {
        public int Id { get; private set; }
        public string Name { get; private set; }
        public string Surname { get; private set; }
        public string Password { get; private set; }
        public string Username { get; private set; }
    }

实体在上下文中映射:

modelBuilder.Entity<User>().Map(map =>
            {
                map.Properties(p => new
                {
                    p.Id,
                    p.Username
                });


                map.ToTable("UserProfile");
            })
                // Map to the Users table
                .Map(map =>
                {
                    map.Properties(p => new
                    {
                        p.Name,
                        p.Surname
                    });

                    map.ToTable("Users");
                }).Ignore(user => user.Photo).HasKey(user => user.Id);

此映射生成的Sql尝试使用一些错误的表名,如User11而不仅仅是User和UserProfile:

SELECT
    [Extent1].[Id] AS [Id],
    [Extent3].[Name] AS [Name],
    [Extent3].[Surname] AS [Surname],
    [Extent1].[Password] AS [Password],
    [Extent2].[Username] AS [Username]
    FROM   [dbo].[User11] AS [Extent1]
    INNER JOIN [dbo].[UserProfile] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Id]
    INNER JOIN [dbo].[Users] AS [Extent3] ON [Extent1].[Id] = [Extent3].[Id]

1 个答案:

答案 0 :(得分:1)

SQL很好。问题实际上在你的映射表达式中。

如果查看映射表达式,则已将所有字段映射到UserUserProfile表,密码除外。这将导致EF6创建一个附加表,并使用自动生成的名称User11来存储非映射属性(密码)。

要确认您可以查看SQL Server中生成的表,您会注意到User11表只有password属性和Id,当您请求上面示例中的所有用户时,EF6正在连接三个表得到结果(User11,User和UserProfile)。

解决方案是更改映射表达式以包含映射中的密码字段,例如:

map.Properties(p => new
{
    p.Id,
    p.Username,
    p.Password
});

这将阻止EF6生成User11表。或者,您可以使用Ignore(p=>p.Password)忽略该属性,但在这种情况下,这不会有任何意义,因为您需要数据库中的密码字段。

如果您不想每次都提取密码字段,那么您可以在查询中明确排除密码字段。