如何从 Entity Framework Core 中的不同上下文加载数据?

问题描述 投票:0回答:1

我有两个数据库,第一个用于用户名及其数据,另一个数据库用于培训,我没有找到一种方法来链接培训表中的受训者和第一个用户数据库中的用户表。使用了两个Context,但我没有找到解决方案。

CentralBase
数据库上下文:

public partial class CentralBase : DbContext
{
    public CentralBase()
    {
    }

    public CentralBase(DbContextOptions<CentralBase> options)
        : base(options)
    {
    }

    public virtual DbSet<AspNetUser> AspNetUsers { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
        => optionsBuilder.UseSqlServer("data source =.\\SQLEXPRESS;initial catalog=CentralBase;integrated security=SSPI;TrustServerCertificate=True");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<AspNetUser>(entity =>
        {
            entity.ToTable("AspNetUser");
            entity.HasKey(e => e.Id);
        });

        OnModelCreatingPartial(modelBuilder);
    }

    partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}

Training
数据库上下文:

public partial class Training : DbContext
{
    public Training()
    {
    }

    public Training(DbContextOptions<Training> options)
        : base(options)
    {
    }

    public virtual DbSet<TrainingPrograme> TrainingPrograme { get; set; }
    
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
        => optionsBuilder.UseSqlServer("data source =.\\SQLEXPRESS;initial catalog=Training;integrated security=SSPI;TrustServerCertificate=True");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<TrainingPrograme>(entity =>
        {
            entity.ToTable("TrainingPrograme");
                entity.HasOne(p => p.AspNetUser)
                .WithMany(u => u.TrainingPrograme)
                .HasForeignKey(p => p.IdUserTraining);
        });


        OnModelCreatingPartial(modelBuilder);
    }

    partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}

AspNetUser

public partial class AspNetUser
{
    [Key]
    public string Id { get; set; } = null!;

    public string? UserName { get; set; }
    public virtual ICollection<EduQ2024.Areas.Train.Data.TableTraining.TrainingPrograme> TrainingPrograme { get; set; } = new List<EduQ2024.Areas.Train.Data.TableTraining.TrainingPrograme>();
}

TrainingPrograme

public partial class TrainingPrograme
{
    public int Id { get; set; }

    public string? IdUserTraining { get; set; }

    public EduQ2024.data.TableCentral.AspNetUser AspNetUser { get; set; }
}

测试代码

Data.DbTraining.Training Cn = new Data.DbTraining.Training();

var f = Cn.TrainingPrograme.ToList();
var g = f.Where(L => L.AspNetUser != null).ToList();.

结果:

AspNetUser = null
c# entity-framework-core
1个回答
0
投票

如果您设置了迁移,您可能会发现 AspNetUsers 表已添加到您的训练数据库中,因为您正在引用该实体。桌子很可能是空的。 AspNetUser 是为认证和授权扩展而定义的默认认证用户表

IdentityDbContext
。这通常不是您想要用于应用程序的
DbContext
,有一个单独的 AppDbContext (TrainingContext) 扩展
DbContext

您可以让多个 DbContext 指向同一数据库中的表,无需使用单独的数据库。因此,例如,如果您实际上不需要单独的数据库,您可以使用 ASP.Net

IdentityDbContext
指向
AspNetUsers
表以及所有角色等进行身份验证和授权,而您的培训应用程序
DbContext
可以映射表中一个单独的、简化的用户实体,通过 Id/Name 以及您从用户的角度可能需要的任何详细信息来表示用户(就训练数据库实体而言)。

如果您确实需要单独的数据库,例如使用每个租户数据库的多租户系统,我建议您设置某种形式的从中央用户数据库到每个租户数据库的复制,其中包含用户 ID 和姓名等详细信息.这在租户(训练)数据库的上下文中可能有用,可以复制下来。这意味着训练数据库可以有一个用户表,其中的 ID 和名称从中央数据库复制下来,以满足 FK 约束等。

因此,从 ASP.Net 身份验证 DbContext 中,AspNetUser 实体将仅包含用于身份验证的属性/引用,而不涉及训练特定细节(例如 TrainingProgrames)。在 TrainingDbContext 中,您可以有一个简化的“用户”实体的

DbSet
,它指向同一个 AspNetUser 表,或者训练数据库中的复制表,其中该实体可以包含用于训练相关项目(如 TrainingProgrames)的多方集合每个用户,同时避免暴露 AspNetAuthentication 数据上下文将使用的身份验证详细信息。身份验证质询将使用 IdentityDbContext,而应用程序特定的数据请求将转到 TrainingDbContext。

// This entity is included in the IdentityDbContext...
[Table("AspNetUsers")]
public class User 
{
     [Key]
     public int Id { get; set; }
     public string? UserName { get; set; }
     // ... other Auth/Identity columns
     public virtual ICollection<Claim> Claims { get; protected set; } = new List<Claim>(); 
     // .. Logins, UserTokens...
}

// This entity for Users is included in the TrainingDbContext 
[Table("AspNetUsers")]
public class TrainingUser
{
     [Key]
     public int Id { get; set; }
     [Column("UserName")]
     public string? EmailAddress { get; set; }
     public string FirstName { get; set; } = string.Empty;
     public string? LastName { get; set; } 

     public virtual ICollection<TrainingProgram> TrainingProgrames { get; protected set; } = new List<TrainingProgram>();
     // Other training related references.
}

例如,Identity DbContext 使用适用于身份验证问题的 AspNetUsers 实体定义。它可以是单个数据库中的同一个表,也可以是中央数据库中的同一个表,作为为训练定义的第二个实体。在这里,我们可以引用 AspNetUsers 表上可能拥有的其他属性(例如用户名),并重新标记 UserName 属性(如果我们打算将其设置为电子邮件地址之类的内容)。培训详细信息不会污染身份实体,并且身份详细信息不会污染,或者存在被来自培训 DbContext 的查询暴露的风险。

虽然单个 DbContext 不能为单个表定义多个实体,但我们可以重新定义要在不同 DbContext 中使用的实体。

© www.soinside.com 2019 - 2024. All rights reserved.