Bug? Ambiguous column name (in Locode)

Solved! Read on for bugfix?

I’ve got at least a couple of services where this happens.

I go in the Locode and choose “select columns”.
If EmpNo is in the select, I get this error:

Ambiguous column name 'EmpNo'.

OrmLite log:

SQL: SELECT TOP 25 "EmpNo", "EmpNo"
FROM "Employee"
ORDER BY "EmpNo"

Used

OrmLiteConfig.BeforeExecFilter = dbCmd => OrmLiteUtils.PrintSql();    // prints every SQL

to get this log.

Query coming from Locode to the server:

https://localhost:5001/api/QueryEmployees?include=total&take=25&fields=EmpNo%2CEmpNo 

400 error.

One such is the employee service. The DTO:

    [Route("/employees", "GET")]
    [Route("/employees/{EmpNo}", "GET")]
    [ValidateRequest("IsAuthenticated")]
    public class QueryEmployees
        : QueryDb<Employee>, IReturn<QueryResponse<Employee>>, IGet
    {
        //public int? EmpNo { get; set; }
    }

is auto generated by going “DB First”, then using the x tool.

I have commented out the public int? EmpNo { get; set; } and also tried commenting out [Route("/employees/{EmpNo}", "GET")] with no improvements.

The underlying Employee class has no double EmpNo columns, but take note that EmpNo is tagged with [PrimaryKey]I removed this, and then the issue was resolved

public class Employee
{
    [AutoIncrement]
    public int MDK { get; set; }

    public string DataSourceId { get; set; }
    public int? ActNo { get; set; }
    [PrimaryKey]
    public int EmpNo { get; set; }

    public int? EmpType { get; set; }
    public string EmpTypeName { get; set; }
    [Required]
    public string FullName { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Mobile { get; set; }
    public string EMail { get; set; }
    public string Title { get; set; }
    public string Room { get; set; }
    public string CountryISOCode { get; set; }
    public string Company { get; set; }

    [ForeignKey(typeof(Department), ForeignKeyName = "DepNo")]
    public int? DepartmentId { get; set; }
    public DateTime? BirthDate { get; set; }
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }
  // ...
    public DateTime? Created { get; set; }
    public DateTime LastModified { get; set; }
    [Required]
    public byte[] RowVersion { get; set; }

    public string MgrPath { get; set; }
    public string JobCode { get; set; }
}
1 Like

I’ve got to re-open this one.
Last time I got it to work by removing [PrimaryKey] on a column, but now it’s back.

This time it’s the column marked [AutoIncrement] which seems to create trouble.

My class:

public class Department
{
    [AutoIncrement]
    public int MDK { get; set; }

    public string DataSourceId { get; set; }   
    public int DepNo { get; set; }

    [Required]
    public string DepName { get; set; }

    public int? MgrEmpNo { get; set; }
    public int? DepParentNo { get; set; }
    public DateTime? Created { get; set; }
    public DateTime? Changed { get; set; }
    public DateTime LastModified { get; set; }

    public int? ReportsToDepNo { get; set; }
    public bool Active { get; set; }
}

Using the
OrmLiteConfig.BeforeExecFilter = dbCmd => OrmLiteUtils.PrintSql(); like before, I see that whenever I select the primary key MDK as one of the columns, it’s listed twice like this:

SQL: SELECT TOP 25 "MDK", "MDK", "DataSourceId"
FROM "Department"
WHERE "Department"."Active" = @0
ORDER BY "MDK"
PARAMS: @0=True

This happens with different classes.

Lets focus on one example so we can try reproducing the issue.

What’s the AutoQuery Request DTO? What’s the Exception? When does this happen, can you provide a screenshot of the custom column selection dialog if that’s when the issue occurs.

Also please confirm if you’re using the latest v6.8

If it doesn’t lead anywhere I’ll see if I can make a repo (but it’s more work, so I’ll try with screenshots first).

// The DTO
    [Route("/departments", "GET")]
    [Route("/departments/{DepNo}", "GET")]
    [ValidateRequest("IsAuthenticated")]
    public class QueryDepartments
        : QueryDb<Department>, IReturn<QueryResponse<Department>>, IGet
    {
        public int? DepNo { get; set; }
        public bool? Active { get; set; }
    }
// auto generated by SS
public class Department
{
    [PrimaryKey]
    [AutoIncrement]
    public int MDK { get; set; }

    public string DataSourceId { get; set; }
    
    public int DepNo { get; set; }

    [Required]
    public string DepName { get; set; }

    public int? DepLevel { get; set; }
    public string DepPath { get; set; }

    public int? MgrEmpNo { get; set; }

    public int? DepParentNo { get; set; }
    public int? DepIdNo { get; set; }
    public int? DepIdSe { get; set; }
    public int? DepIdNl { get; set; }
    public int? EmployeeCount { get; set; }
    public int? EmployeeSubtreeCount { get; set; }
    public DateTime? Created { get; set; }
    public DateTime? Changed { get; set; }
    public DateTime LastModified { get; set; }

    public int? ReportsToDepNo { get; set; }
    public bool Active { get; set; }
}

There’s no custom implementation. My custom implementation uses another DTO:
public QueryResponse<AnnotatedDepartment> Any(QueryDepartmentsPlus request) just for info.

This screenshot should be useful:

Console window:
image

And here’s the metadata:

"request": {
  "name": "QueryDepartments",
  "namespace": "Masterdata.ServiceModel",
  "inherits": {
    "name": "QueryDb`1",
    "namespace": "ServiceStack",
    "genericArgs": [
      "Department"
    ]
  },
  "implements": [
    {
      "name": "IGet",
      "namespace": "ServiceStack",
      "genericArgs": []
    }
  ],
  "properties": [
    {
      "name": "DepNo",
      "type": "Nullable`1",
      "namespace": "System",
      "isValueType": true,
      "genericArgs": [
        "Int32"
      ]
    },
    {
      "name": "Active",
      "type": "Nullable`1",
      "namespace": "System",
      "isValueType": true,
      "genericArgs": [
        "Boolean"
      ]
    }
  ],
  "attributes": [
    {
      "name": "ValidateRequest",
      "args": [
        {
          "name": "Validator",
          "type": "String",
          "namespace": "System",
          "value": "IsAuthenticated"
        }
      ]
    }
  ]
},
"response": {
  "name": "QueryResponse`1",
  "namespace": "ServiceStack",
  "genericArgs": [
    "Department"
  ],
  "implements": [],
  "dataContract": {},
  "properties": [
    {
      "name": "Offset",
      "type": "Int32",
      "namespace": "System",
      "isValueType": true,
      "dataMember": {
        "order": 1
      }
    },
    {
      "name": "Total",
      "type": "Int32",
      "namespace": "System",
      "isValueType": true,
      "dataMember": {
        "order": 2
      }
    },
    {
      "name": "Results",
      "type": "List`1",
      "namespace": "System.Collections.Generic",
      "genericArgs": [
        "Department"
      ],
      "dataMember": {
        "order": 3
      }
    },
    {
      "name": "Meta",
      "type": "Dictionary`2",
      "namespace": "System.Collections.Generic",
      "genericArgs": [
        "String",
        "String"
      ],
      "dataMember": {
        "order": 4
      }
    },
    {
      "name": "ResponseStatus",
      "type": "ResponseStatus",
      "namespace": "ServiceStack",
      "dataMember": {
        "order": 5
      }
    }
  ]
},
"actions": [
  "ANY"
],
"method": "GET",
"returnType": {
  "name": "QueryResponse`1",
  "namespace": "ServiceStack",
  "genericArgs": [
    "Department"
  ]
},
"routes": [
  {
    "path": "/departments",
    "verbs": "GET"
  },
  {
    "path": "/departments/{DepNo}",
    "verbs": "GET"
  }
],
"dataModel": {
  "name": "Department",
  "namespace": "Masterdata.ServiceModel.Types"
},
"viewModel": {
  "name": "Department",
  "namespace": "Masterdata.ServiceModel.Types"
},
"requiresAuth": true
},

Are you using the latest v6.8?

using NuGet

ok thanks, wanted to make sure you’re using the new Vue 3 Locode not the old petite-vue impl. I’ll see if I can repro from this definition.

It looks like you have a mix v6.8.0 from NuGet and v6.8.1 from MyGet when you should always be referencing the same version of ServiceStack to avoid binary incompatibility.

I’d recommend just using a wildcard so it always installs the same (latest) version when you restore.

<PackageReference Include="ServiceStack" Version="6.*" />
1 Like

Managed to repro, thx. This should be resolved from the latest v6.8.1+ that’s now available on MyGet.

You’ll need to clear your NuGet packages cache to download the latest v6.8.1.

1 Like