如何从多个数据库表映射到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]

最佳答案

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

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

为了确认您可以查看SQL Server中生成的表,您会注意到User11表仅具有密码属性和ID,并且当您像上述示例中一样请求所有用户时,EF6将三个表联接起来以获取结果(User11,User和UserProfile)。

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

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


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

然后,如果您不想每次都拉密码字段,则可以在查询中明确排除密码字段。

08-27 01:21