当前位置: 首页 > news >正文

深圳聘请做网站人员大型网站建设方案常见问题

深圳聘请做网站人员,大型网站建设方案常见问题,什么是网络科技公司,如何创立自己的公众号本博文翻译自#xff1a;http://gunnarpeipman.com/2017/08/tenant-providers/ 在我之前关于 Entity Framework core 2.0 全局查询过滤器的文章中#xff0c;我提出了一个想法#xff0c;当构建模型时#xff0c;如何自动地将查询过滤器应用到所有的领域实体中#xff0c…本博文翻译自http://gunnarpeipman.com/2017/08/tenant-providers/ 在我之前关于 Entity Framework core 2.0 全局查询过滤器的文章中我提出了一个想法当构建模型时如何自动地将查询过滤器应用到所有的领域实体中也就是说领域实体总是来自同一租户。这篇文章更深入地介绍了在 ASP.NET Core 应用程序中检测当前租户的可能解决方案并建议一些租户提供者将为实际应用程序中提供多租户的支持作为出发点。 注意! 请阅读我之前在Entity Framework core 2.0 全局查询过滤器中的文章这篇文章将继续下去并期待读者熟悉我为多租户提供的解决方案。另外将多租户规则应用到所有领域实体的方法是从我以前的全局查询过滤器中获取的而不是在这里复制的。 如何检测当前租户? 情况是这样的。数据上下文是在请求传入和构建模型全局查询过滤器时构建的。其中一个过滤器是关于当前租户的。在代码中还需要租户ID但模型还没有准备好。同一时间租户ID只能在数据库中使用。我们该怎么办? 一些想法: 在数据上下文中使用数据库连接并对租户表进行直接查询为租户的信息和操作使用单独的数据上下文保持租户信息在云存储上可用使用域名的哈希值作为租户ID 注意! 在本文中我希望在web应用程序中通过host的header检测租户。 我在这篇文章中使用的租户表如下图所示。 注意! 依赖于解决方案的租户ID也可以是其他的而不是像上图所示的int类型。 使用数据上下文连接数据库 这可能是最轻量级的解决方案了因为不需要添加额外的类也不再需要租户提供程序。而且使用IHttpContextAccessor很容易获得当前host的header。 public class PlaylistContext : DbContext{      private int _tenantId;       private string _tenantHost; public DbSetPlaylist Playlists { get; set; }     public DbSetSong Songs { get; set; }     public PlaylistContext(DbContextOptionsPlaylistContext options,                           IHttpContextAccessor accessor)        : base(options)    {_tenantHost accessor.HttpContext.Request.Host.Value;}     protected override void OnModelCreating(ModelBuilder modelBuilder)      {          var connection Database.GetDbConnection();       using (var command connection.CreateCommand()){connection.Open();command.CommandText select ID from Tenants where HostHost;command.CommandType CommandType.Text; var param command.CreateParameter();param.ParameterName Host;param.Value _tenantHost;command.Parameters.Add(param);_tenantId (int)command.ExecuteScalar();connection.Close();} foreach (var type in GetEntityTypes())        {            var method SetGlobalQueryMethod.MakeGenericMethod(type);method.Invoke(this, new object[] { modelBuilder });} base.OnModelCreating(modelBuilder);} // Other methods follow} 上面的代码是基于数据上下文所持有的数据库连接创建命令并运行sql命令以通过host的header来获取租户ID。 这个解决方案的代码量是比较少的但是它会用主机名检测内部细节的方法来污染数据上下文。 为租户使用单独的数据上下文 第二种方法是使用单独的web应用程序访问特定的租户上下文。可以编写租户提供程序(请参阅我的Entity Framework core 2.0 全局查询过滤器)并将其注入到主数据上下文 让我们从文章开头提到的租户表开始。 public class Tenant{      public int Id { get; set; }      public string Name { get; set; }      public string Host { get; set; } } 现在让我们构建租户数据上下文。这个上下文不依赖于其他有依赖关系的自定义接口和类。它只使用租户模型。请注意租户集是私有的其他类只能通过host的header查询租户ID。 public class TenantsContext : DbContext{      private DbSetTenant Tenants { get; set; } public TenantsContext(DbContextOptionsTenantsContext options)        : base(options)    {}    protected override void OnModelCreating(ModelBuilder modelBuilder)    {modelBuilder.EntityTenant().HasKey(e e.Id);}    public int GetTenantId(string host)    {       var tenant Tenants.FirstOrDefault(t t.Host host);        if(tenant null){            return 0;} return tenant.Id;} } 现在是时候回到ITenantProvider并编写使用租户数据上下文的实现了。这个提供程序包含检测host的header和获取租户ID的所有逻辑在实际应用中它将更加复杂但是在这里我将使用简单的版本。 public class WebTenantProvider : ITenantProvider{    private int _tenantId; public WebTenantProvider(IHttpContextAccessor accessor,                                TenantsContext context)    {           var host accessor.HttpContext.Request.Host.Value;_tenantId context.GetTenantId(host);} public int GetTenantId()    {                return _tenantId;} } 现在需要检查租户并找到它的ID因为已经到了重新编写主数据上下文的时候了所以它使用新的租户提供程序。 public class PlaylistContext : DbContext{      private int _tenantId; public DbSetPlaylist Playlists { get; set; }          public DbSetSong Songs { get; set; }    public PlaylistContext(DbContextOptionsPlaylistContext options,                           ITenantProvider tenantProvider)        : base(options)    {_tenantId tenantProvider.GetTenantId();}    protected override void OnModelCreating(ModelBuilder modelBuilder)    {        foreach (var type in GetEntityTypes())         {  var method SetGlobalQueryMethod.MakeGenericMethod(type);method.Invoke(this, new object[] { modelBuilder });} base.OnModelCreating(modelBuilder);} // Other methods follow} 在web应用程序的启动类中必须在ConfigureServices()方法中 为框架级定义的所有依赖项进行依赖注入。 public void ConfigureServices(IServiceCollection services){services.AddMvc(); var connection Configuration[ConnectionString];services.AddEntityFrameworkSqlServer();services.AddDbContextPlaylistContext(options options.UseSqlServer(connection));services.AddDbContextTenantsContext(options options.UseSqlServer(connection));services.AddScopedITenantProvider, WebTenantProvider();services.AddSingletonIHttpContextAccessor, HttpContextAccessor(); } 这个解决方案更优雅因为它将与租户相关的功能从主数据上下文中移出。ITenantProvider是主数据上下文唯一必须知道的东西现在它也可以在其他不一定是web应用程序的项目中使用。 将租户信息存储在云存储中 我现在说的是租户并不是一直都在使用而不是租户提供程序查询数据库在需要的时候可以缓存租户信息并在需要时更新它。考虑到云的场景最好让租户信息在web应用程序的多个实例中都可以访问。我的选择是云存储。 让我们从json格式的简单的租户文件开始让我们期望它是一些内部应用程序或后台任务的职责以使这个文件保持最新。这是我使用的样本文件。 [{Id: 2,Name: Local host,Host: localhost:30172},{Id: 3,Name: Customer X,Host: localhost:3331},{Id: 4,Name: Customer Y,Host: localhost:33111} ] 要读取云存储应用程序中的文件需要了解存储帐户连接字符串、容器名称和云名称。Blob是租户文件。我再次使用ITenantProvider接口并为Azure 云存储创建了一个新的实现。我把它叫做BlobStorageTenantProvider。它很简单不需要考虑很多实际的方面比如刷新租户信息和处理锁。 public class BlobStorageTenantProvider : ITenantProvider{    private static IListTenant _tenants; private int _tenantId 0; public BlobStorageTenantProvider(IHttpContextAccessor accessor, IConfiguration conf)    {      if(_tenants null){LoadTenants(conf[StorageConnectionString], conf[TenantsContainerName], conf[TenantsBlobName]);} var host accessor.HttpContext.Request.Host.Value;     var tenant _tenants.FirstOrDefault(t t.Host.ToLower() host.ToLower());      if(tenant ! null){_tenantId tenant.Id;}} private void LoadTenants(string connStr, string containerName, string blobName)    {      var storageAccount CloudStorageAccount.Parse(connStr);            var blobClient storageAccount.CreateCloudBlobClient();              var container blobClient.GetContainerReference(containerName);        var blob container.GetBlobReference(blobName);blob.FetchAttributesAsync().GetAwaiter().GetResult(); var fileBytes new byte[blob.Properties.Length]; using (var stream blob.OpenReadAsync().GetAwaiter().GetResult())           using (var textReader new StreamReader(stream))          using (var reader new JsonTextReader(textReader)){_tenants JsonSerializer.Create().DeserializeListTenant(reader);}}        public int GetTenantId()    {            return _tenantId;} } 提供者的代码可能不是很好但是它比以前的代码好因为不需要额外的数据库调用而且租户id是由内存服务的。 用host的header的哈希值作为租户ID 第三种方法是最简单的方法但这意味着租户ID与host的 header相同或者从它派生而来。我不喜欢这种做法因为如果客户想要更改host的 header那么更改将分布在整个数据库中。客户可能希望从服务自动提供的自定义主机名开始然后使用他们自己的子域名。 这里是作为主机名的租户ID的代码。 public class PlaylistContext : DbContext{       private string _tenantId; public DbSetPlaylist Playlists { get; set; }    public DbSetSong Songs { get; set; }    public PlaylistContext(DbContextOptionsPlaylistContext options,                            IHttpContextAccessor accessor)        : base(options)    {_tenantId accessor.HttpContext.Request.Host.Value;}    protected override void OnModelCreating(ModelBuilder modelBuilder)    {        foreach (var type in GetEntityTypes())        { var method SetGlobalQueryMethod.MakeGenericMethod(type);method.Invoke(this, new object[] { modelBuilder });} base.OnModelCreating(modelBuilder);} // Other methods follow} 可以使用MD5代替主机的名称但它不会改变主机的问题。 总结 这篇文章是关于在Entity Framework Core 2.0中真正的去利用全局查询过滤器。虽然这里所展示的代码是简单的而不我们实际运用场景所需要的但在构建真正的解决方案之前它们仍然是很好的例子。我尽量让解决方案尽可能的接近完美的架构原则。我认为读者他们自己的多租户应用程序可以在这里提供的解决方案中获得帮助。 相关文章  .NET Core 2.0 正式发布信息汇总.NET Standard 2.0 特性介绍和使用指南.NET Core 2.0 的dll实时更新、https、依赖包变更问题及解决.NET Core 2.0 特性介绍和使用指南Entity Framework Core 2.0 新特性体验 PHP under .NET Core.NET Core 2.0使用NLog升级项目到.NET Core 2.0在Linux上安装Docker并成功部署解决Visual Studio For Mac Restore失败的问题ASP.NET Core 2.0 特性介绍和使用指南Entity Framework Core 2.0 全局查询过滤器Entity Framework Core 2.0 特性介绍和使用指南 原文地址http://www.cnblogs.com/chen-jie/p/tenant-providers.html .NET社区新闻深度好文微信中搜索dotNET跨平台或扫描二维码关注
http://www.zqtcl.cn/news/213519/

相关文章:

  • 企业做网站要多少钱简单网页设计模板网站
  • 住宅城乡建设部门户网站seo主管的seo优化方案
  • 商洛做网站电话北京做网站比较大的公司
  • 某俄文网站电脑做网站服务器
  • 广州网站建设开发团队江苏省建设招标网站
  • 南昌建设工程质量监督网站wordpress菜单登录
  • 网站设计贵不贵网站seo设置是什么
  • 不属于企业网站建设基本标准的是南通网站建设知识
  • 玉树州wap网站建设公司做试玩网站
  • 商城网站怎么建保定网络营销网站建设
  • 检索类的网站建设公司的网站建设规划书
  • 百度做网站需要交钱吗保定网站建设平台分析
  • 张家界建设局网站电话优化关键词排名公司
  • 宁夏网站建设一条龙网站建设中的图片及视频要求
  • 某些网站dns解析失败湛江制作企业网站
  • 网站开发用什么代码长沙哪家公司做网站
  • 做视频找素材的网站有哪些wordpress 合法评论
  • php网站开发程序填空题高水平网站运营托管
  • 揭东建设局网站wordpress建站后发布
  • 济南哪里有建网站制作视频的手机软件
  • 建设教育网站的国内外研究现状沧州市宇通网站建设公司
  • 大型网站开发框架有哪些厦门外贸网页设计服务
  • 开网站空间流量怎么选择公司注册咨询电话
  • 邢台网站建设基本流程网站制作公司教你怎么制作网站
  • 苏州网站建设方案外包视频网站制作教程视频
  • 呼伦贝尔市规划建设局网站wordpress 主题切换
  • 建设网站的要求吗网站怎么建立
  • 网站结构有哪些建设局平台
  • 高端网站建设公司服务好吗有哪些制作网站的公司
  • 网站整站模板下载工具淮安网站建设案例