C# DbContext模型生成器中的用户详细信息
我对razor pages/efcore/aspnet identity还不熟悉,一直想弄明白这一点,但它打败了我 基本上,我使用AspNet标识进行用户身份验证和授权。我用一个额外的OrganizationID扩展了AspNetUsers,这是一个FK到Organization实体;并将该ID作为声明添加到标识声明存储中。这个很好用 现在,我需要根据经过身份验证的用户的OrganizationID设置一个值,以便他们只能查看分配给其组织的数据 但是,我无法访问ModelBuilder中经过身份验证的用户详细信息C# DbContext模型生成器中的用户详细信息,c#,entity-framework,razor,asp.net-identity,C#,Entity Framework,Razor,Asp.net Identity,我对razor pages/efcore/aspnet identity还不熟悉,一直想弄明白这一点,但它打败了我 基本上,我使用AspNet标识进行用户身份验证和授权。我用一个额外的OrganizationID扩展了AspNetUsers,这是一个FK到Organization实体;并将该ID作为声明添加到标识声明存储中。这个很好用 现在,我需要根据经过身份验证的用户的OrganizationID设置一个值,以便他们只能查看分配给其组织的数据 但是,我无法访问ModelBuilder中经过身份
public class SDMOxContext : IdentityDbContext<
ApplicationUser, ApplicationRole, string,
ApplicationUserClaim, ApplicationUserRole, ApplicationUserLogin,
ApplicationRoleClaim, ApplicationUserToken>
{
public SDMOxContext(DbContextOptions<SDMOxContext> options)
: base(options)
{ }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Set global filter so users can only see projects within their organisation.
builder.Entity<Project>().HasQueryFilter(project => project.OrganisationId == 1);
}
但是,用户在当前上下文中不存在。我建议将解决方案分解为两部分
因此,我需要在稍后阶段应用查询过滤器,即在用户身份验证之后?从哪里开始使用中间层/逻辑层方法 虽然这是一个关于建筑的观点,但我将其分解如下: 数据层-该层负责访问(通常)执行应用程序外部的资源。这包括,;数据库、文件IO、Web Api等 业务/逻辑层-该层的职责(可以进一步细分)应该验证、授权、验证和构建表示业务需求的对象。要构建这些对象,它可能会使用一个或多个数据访问对象(例如,它可能使用IO DA从本地文件系统或Azure存储检索映像,使用数据库DA检索有关该映像的元数据) 表示/公开层-该层的职责是将对象包装并转换为用户需要的内容(winforms、wpf、html、json、xml、二进制序列化等) 通过将逻辑排除在数据层之外(即使在多租户系统中),您可以跨所有系统访问数据(相信我,这里可以赚很多钱) 这可能比我在这么短的时间内所能解释的要多得多,而且我的观点非常强烈。我将略去一些,但现在开始 数据层
namespace ProjectsData
{
public interface IProjectDA
{
IProjectDO GetProject(Guid projectId, Guid organizationId);
}
private class ProjectDA : DbContext, IProjectDA
{
public ProjectDA (...)
public IEnumerable<ProjectDO> Projects { get; set; }
protected override void OnModelCreating(ModelBuilder builder) {... }
public IProjectDO GetProject(Guid projectId, Guid organizationId)
{
var result = Projects
.FirstOrDefault(p => p.Id == projectId && OrganizationId = organizationId);
return result;
}
}
public interface IProjectDO{ ... }
private class ProjectDO: IProjectDO
{
public Guid Id { get; set; }
public Guid OrganizationId { get; set; }
public Guid CategoryId { get; set; }
}
}
名称空间项目数据
{
公共接口IProjectDA
{
IProjectDO GetProject(Guid projectId、Guid organizationId);
}
私有类ProjectDA:DbContext,IProjectDA
{
公共项目a(…)
公共IEnumerable项目{get;set;}
模型创建时受保护的覆盖无效(ModelBuilder){…}
公共IProjectDO GetProject(Guid projectId、Guid organizationId)
{
var结果=项目
.FirstOrDefault(p=>p.Id==projectId&&OrganizationId=OrganizationId);
返回结果;
}
}
公共接口IProjectDO{…}
私有类ProjectDO:IProjectDO
{
公共Guid Id{get;set;}
公共Guid组织ID{get;set;}
公共Guid类别ID{get;set;}
}
}
逻辑
名称空间项目业务
{
公共接口IProjectBO{..}
公共界面组织
{
Guid组织ID{get;}
}
私有类项目BA:IProjectBO
{
私有只读IProjectDA_projectDA;
私有只读身份标识;
私人只读组织;
公共项目逻辑(IProjectDA projectDA,
身份识别,
IOR组织上下文(组织上下文)
{
_projectDA=projectDA;
_身份=身份;
}
公共IProjectBO GetProject(Guid id)
{
var do=\u projectDA
.GetProject(id,组织机构);
var结果=映射到(do);
返回结果;
}
}
公共接口IProjectBO{..}
私有类ProjectBO
{
公共Guid Id{get;set;}
公共Guid组织ID{get;set;}
公共Guid类别ID{get;set;}
}
}
因此,在这些情况下,数据层知道请求的类型,但不知道多租户。它并没有基于任何内容限制所有请求。这种体系结构在许多方面都有优势
首先,在上面的例子中,你的产品起飞了,你的主管想知道哪些类别最受欢迎
namespace StatisticsBusiness
{
public interface IStatisticsBO
{
IEnumerable<ICategoryStatisticBO> CategoryStatistics { get; set; }
}
public interface ICategoryStaticBO
{
Guid CategoryId { get; }
int ProjectCount { get; }
}
private class StatisticsBA : IStatisticsBO
{
private readonly IProjectDA _projectDA;
private readonly IIdentity _identity;
public ProjectLogic(IProjectDA projectDA,
IIdentity identity)
{
_projectDA = projectDA;
_identity = identity;
}
public IEnumerable<IProjectBO GetOrderedCategoryPopularity()
{
var dos = _projectDA
.GetProjectCategoryCounts()
var result = map.To<IEnumerable<IStatisticsBO>>(dos);
return result;
}
}
public interface IStatisticsBO{ .. }
private class StatisticsBO
{
public Guid CategoryId { get; }
public int ProjectCount { get; }
}
}
名称空间统计业务
{
公共接口IStatisticsBO
{
IEnumerable CategoryStatistics{get;set;}
}
公共接口ICategoryStaticBO
{
Guid类别ID{get;}
int ProjectCount{get;}
}
私人统计BA:IStatisticsBO
{
私有只读IProjectDA_projectDA;
私有只读身份标识;
公共项目逻辑(IProjectDA projectDA,
身份(身份)
{
_projectDA=projectDA;
_身份=身份;
}
public IEnumerable将是一个问题。IMHO上下文不应该知道任何关于如何访问它的信息。您应该有一个中间层/逻辑层,该层支持租户应用逻辑(而不是数据层)。因此,我需要在稍后阶段应用查询过滤器,即在用户身份验证之后?是否有任何指针可以从中间层/逻辑层方法开始?感谢Naveddeshmukh,我的第1部分工作正常。只是命名不同,我的租户是OrganizationID,博客实体是项目实体。如果我指定了int per,这将非常有效上面是我的示例。但是,我正在处理第2部分。在实例化dbContext时,我不知道如何传入OrganizationID。OrganizationID可以作为声明(aspnet标识)使用,但我找不到
namespace ProjectBusiness
{
public interface IProjectBO { .. }
public interface IOrganization
{
Guid OrganizationId { get; }
}
private class ProjectBA : IProjectBO
{
private readonly IProjectDA _projectDA;
private readonly IIdentity _identity;
private readonly IOrganization _organization;
public ProjectLogic(IProjectDA projectDA,
IIdentity identity,
IOrganizationContext organizationContext)
{
_projectDA = projectDA;
_identity = identity;
}
public IProjectBO GetProject(Guid id)
{
var do = _projectDA
.GetProject(id, _organization);
var result = map.To<ProjectBO>(do);
return result;
}
}
public interface IProjectBO { .. }
private class ProjectBO
{
public Guid Id { get; set; }
public Guid OrganizationId { get; set; }
public Guid CategoryId { get; set; }
}
}
namespace StatisticsBusiness
{
public interface IStatisticsBO
{
IEnumerable<ICategoryStatisticBO> CategoryStatistics { get; set; }
}
public interface ICategoryStaticBO
{
Guid CategoryId { get; }
int ProjectCount { get; }
}
private class StatisticsBA : IStatisticsBO
{
private readonly IProjectDA _projectDA;
private readonly IIdentity _identity;
public ProjectLogic(IProjectDA projectDA,
IIdentity identity)
{
_projectDA = projectDA;
_identity = identity;
}
public IEnumerable<IProjectBO GetOrderedCategoryPopularity()
{
var dos = _projectDA
.GetProjectCategoryCounts()
var result = map.To<IEnumerable<IStatisticsBO>>(dos);
return result;
}
}
public interface IStatisticsBO{ .. }
private class StatisticsBO
{
public Guid CategoryId { get; }
public int ProjectCount { get; }
}
}