diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Entity.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Entity.cs index cf1b643305..274b4584d1 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Entity.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Entity.cs @@ -7,6 +7,11 @@ namespace Volo.Abp.Domain.Entities [Serializable] public abstract class Entity : IEntity { + protected Entity() + { + EntityHelper.TrySetTenantId(this); + } + /// public override string ToString() { diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs index 4725496a29..e2acfba87c 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs @@ -265,5 +265,25 @@ namespace Volo.Abp.Domain.Entities ? new Type[] { typeof(DisableIdGenerationAttribute) } : new Type[] { }); } + + public static void TrySetTenantId(IEntity entity) + { + if (entity is not IMultiTenant multiTenantEntity) + { + return; + } + + var tenantId = AsyncLocalCurrentTenantAccessor.Instance.Current?.TenantId; + if (tenantId == multiTenantEntity.TenantId) + { + return; + } + + ObjectHelper.TrySetProperty( + multiTenantEntity, + x => x.TenantId, + () => tenantId + ); + } } } diff --git a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AbpMultiTenancyModule.cs b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AbpMultiTenancyModule.cs index c51daf99aa..1a39248631 100644 --- a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AbpMultiTenancyModule.cs +++ b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AbpMultiTenancyModule.cs @@ -18,6 +18,8 @@ namespace Volo.Abp.MultiTenancy { public override void ConfigureServices(ServiceConfigurationContext context) { + context.Services.AddSingleton(AsyncLocalCurrentTenantAccessor.Instance); + var configuration = context.Services.GetConfiguration(); Configure(configuration); } diff --git a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantAccessor.cs b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantAccessor.cs index 32f7fc0782..279e585d26 100644 --- a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantAccessor.cs +++ b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/AsyncLocalCurrentTenantAccessor.cs @@ -3,8 +3,10 @@ using Volo.Abp.DependencyInjection; namespace Volo.Abp.MultiTenancy { - public class AsyncLocalCurrentTenantAccessor : ICurrentTenantAccessor, ISingletonDependency + public class AsyncLocalCurrentTenantAccessor : ICurrentTenantAccessor { + public static AsyncLocalCurrentTenantAccessor Instance { get; } = new(); + public BasicTenantInfo Current { get => _currentScope.Value; @@ -13,7 +15,7 @@ namespace Volo.Abp.MultiTenancy private readonly AsyncLocal _currentScope; - public AsyncLocalCurrentTenantAccessor() + private AsyncLocalCurrentTenantAccessor() { _currentScope = new AsyncLocal(); } diff --git a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/Entity_Tests.cs b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/Entity_Tests.cs index 779ac3fe49..36c65c63a4 100644 --- a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/Entity_Tests.cs +++ b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/Entity_Tests.cs @@ -74,6 +74,23 @@ namespace Volo.Abp.Domain.Entities new Car(42, tenantId1).EntityEquals(new Car(42, tenantId1)).ShouldBeTrue(); } + [Fact] + public void Should_Set_TenantId_On_Object_Creation() + { + var tenantId = Guid.NewGuid(); + AsyncLocalCurrentTenantAccessor.Instance.Current = new BasicTenantInfo(tenantId); + new Car().TenantId.ShouldBe(tenantId); + } + + [Fact] + public void Should_Override_TenantId_Manually() + { + AsyncLocalCurrentTenantAccessor.Instance.Current = null; + + var tenantId = Guid.NewGuid(); + new Car(0, tenantId).TenantId.ShouldBe(tenantId); + } + public class Person : Entity { public Person() @@ -88,7 +105,7 @@ namespace Volo.Abp.Domain.Entities public class Car : Entity, IMultiTenant { - public Guid? TenantId { get; } + public Guid? TenantId { get; private set; } public Car() { diff --git a/framework/test/Volo.Abp.TestApp.Tests/Volo/Abp/TestApp/Application/PersonAppService_Tests.cs b/framework/test/Volo.Abp.TestApp.Tests/Volo/Abp/TestApp/Application/PersonAppService_Tests.cs index 8d205df899..d723184b95 100644 --- a/framework/test/Volo.Abp.TestApp.Tests/Volo/Abp/TestApp/Application/PersonAppService_Tests.cs +++ b/framework/test/Volo.Abp.TestApp.Tests/Volo/Abp/TestApp/Application/PersonAppService_Tests.cs @@ -57,7 +57,7 @@ namespace Volo.Abp.TestApp.Application var uniquePersonName = Guid.NewGuid().ToString(); var personDto = await _peopleAppService.CreateAsync(new PersonDto {Name = uniquePersonName}); - var repository = ServiceProvider.GetService>(); + var repository = ServiceProvider.GetRequiredService>(); var person = await repository.FindAsync(personDto.Id); person.ShouldNotBeNull();