В этой статье мы попытались реализовать поставщика арендаторов на основе базы данных — https://www.codingame.com/playgrounds/5440/multi-tenant-asp-net-core-2---implementing-database-based-арендатор-поставщик ... и у него есть 2 контекста базы данных ApplicationDbContext и MultiTenantDbContext.
Нам удалось сделать add-migration init and update-database
для ApplicationDbContext, НО мы могли НЕ сделать 2-й для MultiTenantDbContext ... и он продолжает говорить о проблеме со ссылкой на объект, не установленной на экземпляр объекта, который связан с `var host = accessor.HttpContext.Request.Host.Value; на /Models/Tenant.cs ниже.
Также мои 2-е вопросы, я не понимаю, почему этот класс DatabaseTenantProvider выполняется в инициализации добавления-миграции в MultiTenantDbContext?!?!
Любые идеи?
Вот код:
/Models/Tenant.cs:
using AthlosifyCore.Data;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace AthlosifyCore.Models
{
public class Tenant
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string HostName { get; set; }
}
public interface ITenantProvider
{
Guid GetTenantId();
}
public class DatabaseTenantProvider : ITenantProvider
{
private Guid _tenantId;
public DatabaseTenantProvider(ApplicationDbContext context, IHttpContextAccessor accessor)
{
var host = accessor.HttpContext.Request.Host.Value;
context.AddSampleData();
// This is for real life cases
//_tenantId = context.Tenants.First(t => t.HostName == host).Id;
_tenantId = context.Tenants.First(t => t.HostName == "imaginary.example.com").Id;
}
public Guid GetTenantId()
{
return _tenantId;
}
}
}
/Data/ApplicationDbContext.cs:
using System;
using System.Collections.Generic;
using System.Text;
using AthlosifyCore.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace AthlosifyCore.Data
{
public class ApplicationDbContext : IdentityDbContext
{
private readonly IHttpContextAccessor _httpContextAccessor;
public DbSet<Tenant> Tenants { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options,
IHttpContextAccessor httpContextAccessor)
: base(options)
{
_httpContextAccessor = httpContextAccessor;
}
public void AddSampleData()
{
Tenants.Add(new Tenant
{
Id = MultitenantDbContext.Tenant1Id,
Name = "Imaginary corp.",
HostName = "imaginary.example.com"
});
Tenants.Add(new Tenant
{
Id = MultitenantDbContext.Tenant2Id,
Name = "The Very Big corp.",
HostName = "big.example.com"
});
SaveChanges();
}
}
}
/Data/MultitenantDbContext.cs:
using AthlosifyCore.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AthlosifyCore.Data
{
public class MultitenantDbContext : DbContext
{
public static Guid Tenant1Id = Guid.Parse("51aab199-1482-4f0d-8ff1-5ca0e7bc525a");
public static Guid Tenant2Id = Guid.Parse("ae4e21fa-57cb-4733-b971-fdd14c4c667e");
public DbSet<Person> People { get; set; }
private ITenantProvider _tenantProvider;
public MultitenantDbContext(DbContextOptions<MultitenantDbContext> options,
ITenantProvider tenantProvider) : base(options)
{
_tenantProvider = tenantProvider;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Person>().HasQueryFilter(p => p.TenantId == _tenantProvider.GetTenantId());
}
public void AddSampleData()
{
People.Add(new Person
{
Id = Guid.Parse("79865406-e01b-422f-bd09-92e116a0664a"),
TenantId = Tenant1Id,
FirstName = "Gunnar",
LastName = "Peipman"
});
People.Add(new Person
{
Id = Guid.Parse("d5674750-7f6b-43b9-b91b-d27b7ac13572"),
TenantId = Tenant2Id,
FirstName = "John",
LastName = "Doe"
});
People.Add(new Person
{
Id = Guid.Parse("e41446f9-c779-4ff6-b3e5-752a3dad97bb"),
TenantId = Tenant1Id,
FirstName = "Mary",
LastName = "Jones"
});
SaveChanges();
}
}
}