Influence on order of columns when using inheritance

Is there a possibility to hint with an attribute for example in what order a table is created when that table inherits from a class?

public class BaseTable
{
  [PrimaryKey]
  public string Id {get;set;}

  public DateTime Updated {get;set;}
}
public class Document : BaseTable
{
  public string Name {get;set;}
}

When I use CreateTableIfNotExists<Document> it creates a table:

Name
Id
Updated

If I later add a new column it is appended at the end = which is OK.

Would be nice if inherited columns/fields are generated FIRST, or at least if it possible to create a hint for it.

Thanks if you make this possible!

I found this commit

that could help me implement the order as I want.

Any idea when this will be available in Nuget?

I tried this already with 5.1.1 from MyGet.
For Sql it seems that this is never called:

You’re referencing the SqlServer2014OrmLiteDialectProvider overrided impl, are you using SqlServer2014Dialect.Provider?

Tried it on all SqlServer dialects, but from the code, it’s not used in these provider.
The commit also shows only Firebird, MySql and Oracle providers that are now using the mentioned Action.
For now I created an implementation for Sql where I just override the ToCreateTableStatement myself.

Would you accept a PR where this is implemented in a more generic way?
Was thinking of this place:

  • adding an extra attribute in the DataAnnotation namespace (ColumnOrder for example)
  • checking on each property for this attribute; if found use order value (int), if not found use 99999 as value
  • if any order found, sort the modelDef.FieldDefinitions list before leaving the function.

As said the above implementation I now used in my custom Sql provider; it makes it possible to decide whether the inherited properties are first or last in the table creation. Let me know.

What are you using for specifying ordering [DataMember(Order = n)? Can you provide an example of one of your tables that’s ordered.

Sounds like you may as well use int.MaxValue instead of some arbitrary number.

I’ll happily take a PR for this if it’s not too disruptive.

An example for following:

public class PocoBase
{
  [PrimaryKey]
  public Guid Id { get; set; }
}

public class Poco : PocoBase
{
  public string Name { get; set; }
}

When you call db.CreateTableIfNotExists<Poco>(); following table is created: (pseudo)

create table Poco
(
  Name varchar(8000),
  Id   uniqueidentifier not null
    primary key
)

In this case I want the Id column to be first and then Name.

Using [DataMember(Order = 1) on the Id and [DataMember(Order = 999)] on the Name did not change the order.

But sometimes you have for example:

public class AuditBase
{
  public DateTime Updated { get; set; }
}

public class Poco : AuditBase
{
  public int Id { get; set; }
  public string Name { get; set; }
}

and in this case you want:

create table Poco
(
  Id int not null primary key,
  Name varchar(8000),
  DateTime datetime
)

Does this make sense?

So you want to use:

public class PocoBase
{
  [DataMember(Order = 1)]
  [PrimaryKey
  public Guid Id { get; set; }
}

public class Poco : PocoBase
{
  [DataMember(Order = 999)]
  public string Name { get; set; }
}

But adding [DataMember] on your classes also changes serialization behavior which makes serialization of fields opt-in so I don’t want to use it for OrmLite.

Since it’s rare, at this point I’ll just call a custom OrmLiteConfig.OnModelDefinitionInit callback added in this commit so you can choose to sort the field definitions using your preferred technique.

Ok… understood… let me know when this commit is available on myget. Thanks.

It’s already on MyGet.

I see 5.1.1 on MyGet, which does not have OrmLiteConfig.OnModelDefinitionInit … Am I looking wrong? https://www.myget.org/F/servicestack

You likely had v5.1.1 already installed so you would need to clear your NuGet cache:

$ nuget locals all -clear

Ok cool!
That is what I need! This feature works now so I can create my own kind of logic for ordering columns towards the DB!

1 Like