Base solution for your next web application
Open Closed

Creation of OrganizationUnits from SeedHelper #4738


User avatar
0
BobIngham created

I am having problems creating OrganizationUnits when seeding the project.
SeedHelper is a static class so I can not inject a repository, the appservice or the manager.
Inserting using the context is not possible because the entity requires a value for Code.
There is the possibility of adding project dependencies but this would break all separation of concerns. My question is:

How do I create OrganizationUnits during seeding?


6 Answer(s)
  • User Avatar
    0
    aaron created
    Support Team

    From the documentation on Dependency Injection:

    If you are in a static context or can not inject IIocManager, as a last resort, you can use a singleton object IocManager.Instance everywhere.

    using (var organizationUnitManager = IocManager.Instance.ResolveAsDisposable<OrganizationUnitManager>())
    {
        organizationUnitManager.Object.Create(new OrganizationUnit(tenantId, displayName, parentId));
    }
    
  • User Avatar
    0
    BobIngham created

    @aaron - thanks, another piece of magic pulled from the magician's hat!!!! But before you light up that cigar can you tell me why the following code in my InitialOrganizationUnitCreator class fails when trying to add a child organization unit?

    public void Create()
    {
        var root = _context.OrganizationUnits.IgnoreQueryFilters().FirstOrDefault(m => m.TenantId == _tenantId && m.DisplayName == "Acme Care Home");
        if (root == null)
        {
            using (var organizationUnitManager = IocManager.Instance.ResolveAsDisposable<OrganizationUnitManager>())
            {
                organizationUnitManager.Object.Create(new OrganizationUnit(_tenantId, "Acme Care Home", null));
            }
        }
        _context.SaveChanges();
        root = _context.OrganizationUnits.IgnoreQueryFilters().FirstOrDefault(m => m.TenantId == _tenantId && m.DisplayName == "Acme Care Home");
    
        var admissions = _context.OrganizationUnits.IgnoreQueryFilters().FirstOrDefault(m => m.TenantId == _tenantId && m.DisplayName == "Admissions");
        if (admissions == null)
        {
            using (var organizationUnitManager = IocManager.Instance.ResolveAsDisposable<OrganizationUnitManager>())
            {
                organizationUnitManager.Object.Create(new OrganizationUnit(_tenantId, "Admissions", root.Id));
            }
        }
    }
    
  • User Avatar
    0
    aaron created
    Support Team

    Fails how? Is it due to unit of work?

  • User Avatar
    0
    BobIngham created

    Wow, Aaron, thanks for the speedy reply, I kind of had this set aside until Monday! The error is unusual, here is a screen capture from VS 2017: [attachment=0:191pkgx2]Capture.PNG[/attachment:191pkgx2] No error is thrown in the log (I don't think the system has hit the logger at this stage if I'm not mistaken). The root organization unit exists in the database (from a previous run). The stack trace reads:

    "   at Abp.Domain.Repositories.AbpRepositoryBase`2.&lt;GetAsync&gt;d__21.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Abp.Threading.InternalAsyncHelper.&lt;AwaitTaskWithPostActionAndFinallyAndGetResult&gt;d__5`1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Abp.Organizations.OrganizationUnitManager.<GetCodeAsync>d__9.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Abp.Organizations.OrganizationUnitManager.<GetNextChildCodeAsync>d__7.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Abp.Organizations.OrganizationUnitManager.<CreateAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Abp.Threading.InternalAsyncHelper.<AwaitTaskWithPostActionAndFinally>d__1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Nito.AsyncEx.Synchronous.TaskExtensions.WaitAndUnwrapException(Task task)\r\n   at Nito.AsyncEx.AsyncContext.<>c__DisplayClass15_0.<Run>b__0(Task t)\r\n   at System.Threading.Tasks.ContinuationTaskFromTask.InnerInvoke()\r\n   at System.Threading.Tasks.Task.Execute()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Nito.AsyncEx.Synchronous.TaskExtensions.WaitAndUnwrapException(Task task)\r\n   at Nito.AsyncEx.AsyncContext.Run(Func`1 action)\r\n   at Abp.Organizations.OrganizationUnitManagerExtensions.Create(OrganizationUnitManager manager, OrganizationUnit organizationUnit)\r\n   at Nuagecare.Migrations.Seed.Tenants.InitialChildOrganizationUnitCreator.Create()\r\n   at Nuagecare.Migrations.Seed.Tenants.DefaultTenantDataBuilder.CreateChildTables()\r\n   at Nuagecare.Migrations.Seed.Tenants.DefaultTenantDataBuilder.Create()\r\n   at Nuagecare.Migrations.Seed.SeedHelper.SeedHostDb(NuagecareDbContext context)\r\n   at Nuagecare.Migrations.Seed.SeedHelper.WithDbContext[TDbContext](IIocResolver iocResolver, Action`1 contextAction)\r\n   at Nuagecare.Migrations.Seed.SeedHelper.SeedHostDb(IIocResolver iocResolver)\r\n   at Nuagecare.EntityFrameworkCore.NuagecareEntityFrameworkCoreModule.PostInitialize()\r\n   at Abp.Modules.AbpModuleManager.<>c.<StartModules>b__15_2(AbpModuleInfo module)\r\n   at System.Collections.Generic.List`1.ForEach(Action`1 action)\r\n   at Abp.Modules.AbpModuleManager.StartModules()\r\n   at Abp.AbpBootstrapper.Initialize()"
    

  • User Avatar
    0
    aaron created
    Support Team

    Disable filter:

    using (var scope = IocManager.Instance.CreateScope())
    {
        var organizationUnitManager = scope.Resolve<OrganizationUnitManager>();
        var unitOfWorkManager = scope.Resolve<IUnitOfWorkManager>();
    
        using (unitOfWorkManager.Current.DisableFilter(AbpDataFilters.MayHaveTenant))
        {
            organizationUnitManager.Create(new OrganizationUnit(_tenantId, "Admissions", root.Id));
        }
    }
    
  • User Avatar
    0
    BobIngham created

    Aaron, Once again I am in your debt. I'm not a great coder and at some stage I will sit down and try understand the details. To close the issue I include the finished code below, I am sure this is a very common use case.

    public void Create()
    {
        var root = _context.OrganizationUnits.IgnoreQueryFilters().FirstOrDefault(m => m.TenantId == _tenantId && m.DisplayName == "Acme Care Home");
        if (root == null)
        {
            using (var organizationUnitManager = IocManager.Instance.ResolveAsDisposable<OrganizationUnitManager>())
            {
                organizationUnitManager.Object.Create(new OrganizationUnit(_tenantId, "Acme Care Home", null));
            }
        }
        _context.SaveChanges();
        root = _context.OrganizationUnits.IgnoreQueryFilters().FirstOrDefault(m => m.TenantId == _tenantId && m.DisplayName == "Acme Care Home");
    
        using (var scope = IocManager.Instance.CreateScope())
        {
            var organizationUnitManager = scope.Resolve<OrganizationUnitManager>();
            var unitOfWorkManager = scope.Resolve<IUnitOfWorkManager>();
    
            using (unitOfWorkManager.Current.DisableFilter(AbpDataFilters.MayHaveTenant))
            {
                var admissions = _context.OrganizationUnits.IgnoreQueryFilters().FirstOrDefault(m => m.TenantId == _tenantId && m.DisplayName == "Admissions");
                if (admissions == null)
                {
                    organizationUnitManager.Create(new OrganizationUnit(_tenantId, "Admissions", root.Id));
                }
    
                var firstFloor = _context.OrganizationUnits.IgnoreQueryFilters().FirstOrDefault(m => m.TenantId == _tenantId && m.DisplayName == "First Floor");
                if (firstFloor == null)
                {
                    organizationUnitManager.Create(new OrganizationUnit(_tenantId, "First Floor", root.Id));
                }
    
                var secondFloor = _context.OrganizationUnits.IgnoreQueryFilters().FirstOrDefault(m => m.TenantId == _tenantId && m.DisplayName == "Second Floor");
                if (secondFloor == null)
                {
                    organizationUnitManager.Create(new OrganizationUnit(_tenantId, "Second Floor", root.Id));
                }
            }
        }
    }
    

    Thanks again.