首页 > 解决方案 > 如何实现访问同一个表但排除某些数据的“标题”基类

问题描述

我有一个现有的表 - 例如

create table Users (
  Id Int,
  UserId varchar(10),
  FirstName nvarchar(30),
  MiddleName nvarchar(30),
  LastName nvarchar(30),
  BirthDate datetime,
  ProfilePicture varbinary(max),
  HeaderPicture varbinary(max)
);

由于ProfilePictureHeaderPicture很大,如果不需要它们,我不想检索它们。以可读性和防止 NullReferenceExceptions 的名义,我想使用两个不同的类——一个只有“标题”信息,一个有完整信息。

以下是我的想法:

[Table("Users")]
public class UserHeader
{
    [Key, Display(AutoGenerateField = false)]
    [Required]
    public int Id { get; set; }

    [Required, StringLength(10)]
    public string UserId { get; set; }

    [Required, StringLength(30)]
    public string FirstName { get; set; }

    [StringLength(30)]
    public string MiddleName { get; set; }

    [Required, StringLength(30)]
    public string LastName { get; set; }

    [Required]
    public DateTime BirthDate { get; set; }
}

public class User : UserHeader
{
    public byte[] ProfilePicture { get; set; }
    public byte[] HeaderPicture { get; set; }
}

当我尝试使用它时,我收到一个错误,即我的表中没有鉴别器列。如果我添加HasNoDiscriminator()到模型构建器,我会得到一个不同的错误:

实体类型“IncidentHeader”是层次结构的一部分,但没有配置鉴别器属性

我不想要一个鉴别器——每一行都应该可以作为 User 和 UserHeader 检索,这取决于使用哪个 DBSet 来访问它。

有什么方法可以使用 EntityFramework Core 实现这种设置?

标签: c#sql-serverentity-framework-core

解决方案


尝试以下方法

public class UserHeader
{
    public int Id { get; set; }
    public string UserId { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
    public User User { get; set; }
}

public class User
{
    public int Id { get; set; }
    public byte[] ProfilePicture { get; set; }
    public byte[] HeaderPicture { get; set; }
}

使用 fluent 接口将这两个类映射到单个表。

public class DB : DbContext
{
    public DbSet<UserHeader> UserHeaders { get; set; }
    public DbSet<User> Users { get; set; }
        
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<UserHeader>(uh =>
        {
            uh.ToTable("Users");

            uh.HasOne(uh => uh.User).WithOne()
                .HasForeignKey<User>(u => u.Id);
        });

        modelBuilder.Entity<User>(user =>
        {
            user.ToTable("Users");
        });
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(
            ConfigurationManager.ConnectionStrings["Database"].ConnectionString);
    }
}

请参阅文档:表拆分


推荐阅读