Base solution for your next web application

Activities of "leonkosak"

One of our customers have multitenant solution with each tenant in separated database. We are now in transition from local environment to Azure (our Azure envoronment vith our host database). The only problem is, that users cannot login in tenant because ASP.NET Zero cannot authenticate (Login failed error). I can see logs (AbpAuditLogs table) in each tenant database (for login failed), so the database for tenant is resolved correctly in Azure environment. I tried to set correct new TenantId in each table (because we just move tenant databases in existing environment in Azure and not host database in local environment).

We tried to update all TenantId values in tenant databases, but it does not help.

What can we do now? What steps are required to move tenant database to other environment.

Thank you for suggestions.

Basically, my stupidity. We moved the current database from a local environment to Azure and then created a new tenant with the connection string to this database. But the tenant id was different from the value in the new host environment.

Correct steps:

  • Create a blank new database in a new environment
  • Create a new tenant in a new environment with a connection string to this blank database
  • Restore existing tenant database to the new environment
  • In all tables with TenantId column in a database, update value to new tenant id value

Of course, the version of an application (and database) has to be the same during migration.

Situation: There is varbinary column in database table and inserting (uploading file) is really fast (9MB), but when reading only one record, the response is very slow. There is aprox. 9MB file in varbinary column but it takes 60-70 seconds in our local environment that postman returns response. in AuditLogs, the time is aprox. 6-7 seconds (which is still a lot).

I donn't know why there is so much difference between ecetution time in AuditLogs table and in reality. I cannot explain either why inserting is so much faster.

AppService


[HttpGet]
        public async Task<MobileReleaseListDto> GetMobileRelease(int versionCode = 0)
        {
            //var release = from mr in _mobileReleaseRepository.GetAll()
            //              where mr.VersionCode > versionCode && mr.Active
            //              orderby mr.VersionCode descending
            //              select mr;
            var release = _mobileReleaseRepository.GetAll()
                .Where(x => x.VersionCode > versionCode && x.Active)
                .OrderByDescending(x => x.VersionCode);
            var lastFile = await release.FirstOrDefaultAsync();
            if (lastFile != null)
            {
                return ObjectMapper.Map<MobileReleaseListDto>(lastFile);
            }
            else
                return new MobileReleaseListDto();
        }

Database table:


[Table("tMobileRelease")]
    public class MobileReleaseModel : Entity
    {
        public const int MaxVersionNameLength = 8;

        [Required]
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public override int Id { get; set; }

        public int VersionCode { get; set; }

        [StringLength(MaxVersionNameLength)]
        public string VersionName { get; set; }

        public string File { get; set; }

        public bool Active { get; set; }

        public int? TenantId { get; set; }

        public byte[] Bytes { get; set; }
    }

Our local environment is pretty powerful and that is not the problem. In Azure, we cannot get response after 500+ seconds.

Thank you for suggestions.

We will definitely run SQL profiler, but we suspect that this issue is not SQL related. We saw this problem in two different environments (different customers and development environments). Even 2MB file is a poblem (multiple seconds execution time in AbpAuditLogs).

The "Audit Logout" below selected (also CPU: 16, Reads: 18298, Duration: 6743) query is empty.

In AbpAuditLogs table

MSSQL 2016 on relatively powerful hardware (virtual machine is basically not loaded with SQL requests at all).

This times and are for aprox 9MB .apk file

Mapping in AutoMapper (in AppService)

But it takes aprox. 68 seconds that Postman shows result (goes "out" of Loading text).

I saw the similar issues storing pdf and image files (jpg, png) with max size 2MB (other customer, SQL 2017 I think, also not loaded virtual machine) - request takes multiple seconds from start to response. Also simple SQL query, without additional processing (rather than converting received file to byte array) inside API.

Thank you for suggestions.

I have there warings too (also v6.9.1), but not error. That's strange.

Response also takes more than a minute (using stopwatch on my phone) if I call method from swagger (ExecutionDuration in AbpAuditLogs is roughly the same as when calling from Postman).

There is also no difference (execution time, stopwatch time,...) if there is no conversion (byte[] => base64string) in AutoMapper. In postman I can see that we gat base64 representation of bytes.

I found something useful.

[HttpGet]
public async Task<FileDto> GetMobileApk(int versionCode = 0)
{
    var release = _mobileReleaseRepository.GetAll()
        .Where(x => x.VersionCode > versionCode && x.Active)
        .OrderByDescending(x => x.VersionCode);
    var lastFile = await release.FirstOrDefaultAsync();

    var now = DateTime.Now;
    var filename = $"Mobile_Tralala.apk";

    var file = new FileDto(filename, null);

    var filePath = Path.Combine("C:\\Path", file.FileToken);
    File.WriteAllBytes(filePath, lastFile.Bytes);

    return file;
}

The funny part is that now ExecutionDuration time (AbpAuditLogs table) and the time when result is displayed in Postman are almost identical. I can see generated file and is identical that it has to be. Overall execution time (in postman) is basically a little more than SQL query time.

Results:

118MB file: Insert: 2.8s Read: not completed in minutes

23MB file: Insert: 1.2s Read: 25s

9MB file: Insert: 270ms Read: 4s

  1. I don't know what happens (inside API?) that if base64 string (or bytes) are returned that takes 1 minute + for 9MB file, if execution time in AbpAuditLogs is around 6-7 seconds.

  2. I don't know why reading is so much slower than inserting in SQL.

  3. As we can see, that reading bytes from SQL to temp file (creating temp file) is much faster than returning base64 string or bytes in the same controller (app service). I cannot explain that? Maybe disposing on API before client request can be finished?

10 rows and only one has binary data.

[HttpGet]
public async Task<FileDto> GetMobileApk(int versionCode = 0)
{
    var release = _mobileReleaseRepository.GetAll()
        .Where(x => x.VersionCode > versionCode && x.Active)
        .OrderByDescending(x => x.VersionCode)
        .Select(x => new { x.Id, x.Active, x.File, x.TenantId, x.VersionCode, x.VersionName });

    //var id = await release.Select(x => x.Id).FirstOrDefaultAsync();

    var lastFile = await release.FirstOrDefaultAsync(); //await _mobileReleaseRepository.GetAsync(id);

    var now = DateTime.Now;
    var filename = $"Mobile_Tralala.apk";

    var file = new FileDto(filename, null);

    var filePath = Path.Combine("C:\\Path", file.FileToken);
    File.WriteAllBytes(filePath, new byte[9000000]);//File.WriteAllBytes(filePath, lastFile.Bytes);

    return file;
}
  1. Excluding binary data (.Select) greatly improves Execution duration (50-120ms and 120-800ms in Postman) even if aprox 9MB array of bytes is added in file (look code below).

  2. Even if from first query is only Id selected and then passed in GetAsync method, the duration times are the same as before.

Showing 1 to 10 of 55 entries