EF核心实体从不同来源继承而没有歧视

时间:2018-12-07 16:07:37

标签: c# asp.net entity-framework asp.net-core entity-framework-core

我正在尝试使用EF Core配置以下所示的两个实体:

用户:

public class User
{
    public int UserId { get; set; }
    public string Title { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    [Required]
    public string Email { get; set; }

    [NotMapped]
    public string FriendlyIdentifier
    {
        get
        {
            var name = $"{Name} {Surname}";
            if (!string.IsNullOrWhiteSpace(name))
                return name;
            else if (!string.IsNullOrWhiteSpace(Email))
                return Email;
            else
                return UserId.ToString();
        }
    }

    public ICollection<Booking> Bookings { get; set; }
}

用户详细信息:

public class UserDetails : User
{
    public DateTime? LatestBookingDate { get; set; }
}

之所以这样做,是因为我希望能够拉出用户的最新预订日期,而不必拉出所有预订,然后在代码中手动确定最新的预订日期。为此,我创建了一个SQL视图,该视图选择了最新的预订日期,并且我想将UserDetails绑定到该视图。

我有以下EF设置:

modelBuilder.Entity<User>(builder =>
{
    builder.ToTable("userdetails");
    builder.HasKey(x => x.UserId);
    builder.HasIndex(x => new { x.Name, x.Surname, x.Email });
});

modelBuilder.Query<UserDetails>()
    .ToView("view_userdetails");

但这在尝试选择UserDetails实体时会出现以下错误:

  

'无法将'User'设置为'UserDetails'的基本类型。遗产   层次结构不能包含实体类型和查询类型的混合。'

我知道这里有一个HasDiscriminator扩展名:https://docs.microsoft.com/en-us/ef/core/modeling/relational/inheritance,但我并没有真正的鉴别符,因为UserDetails只是User的扩展名

我有什么办法让它正常工作吗?我并不是很想将User的属性复制到UserDetails中,因为当发生任何更改时,有两个实体需要维护。我想保留继承。

1 个答案:

答案 0 :(得分:5)

  

我想保留继承。

您不能(至少现在不是这样)。异常消息清楚地表明了这一点-它说“不能包含混合物”,并且没有为您提供建议。

您可以做的是将当前的User类成员移到新的 non实体 non query 类型的类中,并让{{1 }}实体和User查询类型继承自它,例如:

UserDetails

这将使您可以在一个地方维护通用模型。缺点是public abstract class UserInfo { public int UserId { get; set; } public string Title { get; set; } public string Name { get; set; } public string Surname { get; set; } [Required] public string Email { get; set; } [NotMapped] public string FriendlyIdentifier { get { var name = $"{Name} {Surname}"; if (!string.IsNullOrWhiteSpace(name)) return name; else if (!string.IsNullOrWhiteSpace(Email)) return Email; else return UserId.ToString(); } } public ICollection<Booking> Bookings { get; set; } } public class User : UserInfo { } public class UserDetails : UserInfo { public DateTime? LatestBookingDate { get; set; } } 不能在期望UserDetails的地方使用,并且必须进行转换(尽管由于所有通用属性都相同,所以这应该是微不足道的“自动”任务对于AutoMapper)。

请注意,此解决方案要求您在查询类型中User导航属性Ignore

Bookings

或将其移动到modelBuilder.Query<UserDetails>(builder => { builder.ToView("view_userdetails"); builder.Ignore(e => e.Bookings); }); 实体。