V11.0 MVC Core
I created a domain service, and it's called by a background job.
Everything works fine.
I want to log output to the application log file specified in the log4net configuration.
I follow the instructions here: aspnetboilerplate logging documentation as instructed to by documentation here: AspNetZero Core MVC Documentation on logging
I did this:
using Abp.Dependency;
using nameSpace.Surpath.Importing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Castle.Core.Logging;
namespace nameSpace.Surpath.DomainServices
{
public class ImportClientFromSPLService : nameSpaceServiceBase, IImportClientFromSPLService, ISingletonDependency
{
public ILogger Logger { get; set; }
public bool CanImport { get; set; } = true;
public ImportClientFromSPLService()
{
Logger = NullLogger.Instance;
}
public async Task<bool> DoImport(JobArguments args)
{
if (CanImport)
{
Logger.Debug($"DoImport called (Starting): client_id= {args.client_id}");
CanImport = false;
return true;
Thread.Sleep(10000);
Logger.Debug($"DoImport called (Finished): client_id= {args.client_id}");
CanImport = true;
}
else
{
Logger.Debug($"DoImport called (Busy): client_id= {args.client_id}");
return false;
}
}
}
}
I run it, my "DoImport" method is called, and nothing is logged in my Logs.txt file.
I'm obviously doing something really silly here, missing something very basic.
Any suggestions why this doesn't work?
To clarify, here's what I'm trying to do:
I have a legacy, non aspnetzero project. I am trying to import data from the old system into this new project.
First, I have to create a client and admin user, then I have to create some default entities, then I have to create the users from the old system, and import data from there. This data includes large binary objects (PDFs, for example).
This process takes a significant amount of time. If I do this in the migrator, it succeeds because it locks the database and imports the data.
While this works, it makes applying updates painfully slow and makes me take down the system to import more data. One cient import can take as long as 30 minutes.
First challenge is if I create the tenant with an admin user, the app services complain that the user I try and use to import objects doesn't have permissions.
For example, if my UOW uses the create tenent with admin user. This succeeds, but I cannot create a new UOW, tell the session to use that new admin's ID to create entities. I get 'not authorized'.
That entire job has to 'complete' before the application services will "see" the new admin user and their permissions.
I'm not sure, but I think this is because the background job is run as a unit of work.
Secondly, when importing the large files, as a single unit of work, the page for the entity is unresponsive (likely the table is locked).
Lastly, this import takes a long time. If I do it as a background task, the engine tries to run the task before it completes again. This makes me think I should have my background register as a singleton? Maybe have two - where a singleton kicks off the import and returns success as having run? I'm not sure.
The goal is, as host, to kick off an import from the old system after it launches, and have the job create the tenant and setup the users, etc.
As a background task this takes way too long. As a migration task this takes way too long.
I need to find a way to manually start this process after the system starts, and have it run in the background and be allowed to finish without timing out or running again.
I think my singleton "import manager" approach is the way, but I'm just not sure how to get there yet.
Maybe a singletone migrate control in the framework core project. Then, in core, a domain service that uses that. Then, I'd have a backgroundjob that could be started, that'd use the domain service. Since the migrate control is a singleton, the domain service would start an import, or fail if one is already running (based on migrate control's state).
the migrate control singleton could then use units of work to go through each step, each account, each entity.
Does this sound like a sound approach?
This is a good idea.
11.0 CORE MVC
I have background job that is pulling data - this is what I'm doing to try and shuffle a considerable amount of data over.
So I have this repeating over and over in the code, making it smell very bad.
I think I've missed something, this seems way too complicated?
Probably the thing to do is refactor this in a service.
Thanks in advance for any tips or tricks!
using (var uowManager = IocManager.Instance.ResolveAsDisposable<IUnitOfWorkManager>())
{
using (var permUow = uowManager.Object.Begin())
{
_context = uowManager.Object.Current.GetDbContext<inzibackendDbContext>(MultiTenancySides.Host);
if (_context.Tenants.AsNoTracking().IgnoreQueryFilters().Any(t => t.TenancyName.Equals(_args.NewTenancyName)))
return false;
using (var _sessionObj = IocManager.Instance.ResolveAsDisposable<IAbpSession>())
{
_session = _sessionObj.Object;
_session.Use(args.TenantId, args.UserId);
//// Business steps here that create the rec object
_context.Records.Add(rec);
_context.SaveChanges();
}
await permUow.CompleteAsync();
}
}
11.0 MVC Core
We have an older system and I'm trying to move customers to the new one.
I am able to get the data, and create entities, etc. However, I made a job that creates the tenant with an admin user via the tenant app service.
Inside the Unit Of Work Im using ISession and telling it to use null as the tenantID and my Id as the user id.
When the Unit Of Work for that is completed, then I then try to set the session to that new tenant id and the id of the created admin user.
I can see the entity in the database.
When I try and create entities (using the entities' app services) - I get exceptions of not authorized.
If I do it as my, it sets the tenant ID to null on the objects.
I'm really struggling to get this to work - any suggestions would be helpful.
Thanks.
I determined why: I was importing a project into the .core project and it downgraded TZConvert.
I made sure my imported project's csproj file, packages, etc were as identical to .core as I could - and in doing so, the TZConvert is behaving as expected.
Therefore, shedspotter, check your nuget packages, and more in the csproj file - in the event you're importing a project or a package downgraded your TZConvert.
What's interesting, is if I move that function from the TimeZoneService, and run it inside the TimingAppService, it works fine.
Only when it's under Core project does it fail.
I too get an error. V11 MVC Jquery
System.MissingMethodException
HResult=0x80131513
Message=Method not found: 'System.Collections.Generic.ICollection`1<System.String> TimeZoneConverter.TZConvert.get_KnownWindowsTimeZoneIds()'.
Source=inzibackend.Core
StackTrace:
at inzibackend.Timing.TimeZoneService.GetWindowsTimezones() in C:\Dev\Surpathv2\src\inzibackend.Core\Timing\TimeZoneService.cs:line 76
at inzibackend.Timing.TimingAppService.<GetTimezoneInfos>d__4.MoveNext() in C:\Dev\Surpathv2\src\inzibackend.Application\Timing\TimingAppService.cs:line 50
This exception was originally thrown at this call stack:
inzibackend.Timing.TimingAppService.GetTimezoneInfos(Abp.Configuration.SettingScopes) in TimingAppService.cs
This is the function that throws:
return TZConvert.KnownWindowsTimeZoneIds.OrderBy(tz => tz)
.Select(tz => new NameValueDto
{
Value = tz,
Name = TZConvert.GetTimeZoneInfo(tz).DisplayName
}).ToList();
Haven't resolved it yet.
I too get an error. V11 MVC Jquery
System.MissingMethodException
HResult=0x80131513
Message=Method not found: 'System.Collections.Generic.ICollection`1<System.String> TimeZoneConverter.TZConvert.get_KnownWindowsTimeZoneIds()'.
Source=inzibackend.Core
StackTrace:
at inzibackend.Timing.TimeZoneService.GetWindowsTimezones() in C:\Dev\Surpathv2\src\inzibackend.Core\Timing\TimeZoneService.cs:line 76
at inzibackend.Timing.TimingAppService.<GetTimezoneInfos>d__4.MoveNext() in C:\Dev\Surpathv2\src\inzibackend.Application\Timing\TimingAppService.cs:line 50
This exception was originally thrown at this call stack:
inzibackend.Timing.TimingAppService.GetTimezoneInfos(Abp.Configuration.SettingScopes) in TimingAppService.cs
This is the function that throws:
return TZConvert.KnownWindowsTimeZoneIds.OrderBy(tz => tz)
.Select(tz => new NameValueDto
{
Value = tz,
Name = TZConvert.GetTimeZoneInfo(tz).DisplayName
}).ToList();
Haven't resolved it yet.
Core MVC v11.0
I have an entity with a file property, which the system puts in appbinaryobjects table.
When getting results, the created service goes and gets each binaryobject and then only uses the description. This is extremely slow.
So I'm doing this:
desc = _binaryObjectRepository.Get(id).Description;
This has helped - is there a better way to do this? I see there's a .Query on the IRepository - but I'm not sure how to use it.
Any faster way you might suggest?
I found the best way: desc = _binaryObjectRepository.Query<string>(q => q.Where(r => r.Id == id).Select(r => r.Description).FirstOrDefault());
In the above example, it still seleted all columns. The above generates a query similar to this (mysql):
select a.Descriptions from AppBinaryObjects as a where (false or (a.TenantId=5213)) AND (a.Id = '<guid>') limit 1