Miroslav Holec
Premium

EF Core 6 a zákeřný Column Order

Miroslav Holec   1. prosince 2021

Tento článek byl napsán v roce 2021. Vývojářské technologie se neustále inovují a článek již nemusí popisovat aktuální stav technologie, ideální řešení a můj současný pohled na dané téma.

Jedno z nepatrných vylepšení EF Core 6 spočívá v možnosti nastavit si pořadí sloupečků v databázi pomocí atributu Column. Můžeme mít properties v rámci třídy v jednom pořadí a v databázi v pořadí jiném. Doposud jsem to nepoužíval ani ve fluent api, ale teď jsem zjistil, že to má zajímavé chování.

Jak to funguje

Za normálních okolností je dáno pořadí sloupečků v DB pořadím properties v rámci třídy. Takže pro:

public class Webinar
{
    public int Id { get; set; }

    [Unicode]
    public string Title { get; set; }

    [Precision(14,2)]
    public decimal Price { get; set; }

    public DateTime PublicFrom { get; set; }
}

je pořadí: Id, Title, Price, PublicFrom. To asi nepřekvapí.

Zběhlý vývojář také ví, že EF Core upřednostní klíč. Takže když pořadí properties otočíme takto:

public class Webinar
{
    [Unicode]
    public string Title { get; set; }

    public int Id { get; set; }

    [Precision(14,2)]
    public decimal Price { get; set; }

    public DateTime PublicFrom { get; set; }
}

výsledek bude úplně stejný a pořadí sloupečků bude opět: Id, Title, Price, PublicFrom. To je asi dobře, protože klíč chceme vidět jako první sloupec.

Column(Order)

Od EF Core 6 máme k dispozici novou vlastnost Order, kterou najdeme u atributu Column. Takže pořadím můžeme zamávat. Podívejte se na další příklad a zkuste odhadnout pořadí sloupečků v databázi:

public class Webinar
{
    [Unicode]
    public string Title { get; set; }

    [Precision(14,2)]
    public decimal Price { get; set; }

    public int Id { get; set; }

    [Column(Order = 2)]
    public DateTime PublicFrom { get; set; }
}

Máme tedy Id, který EF Core rád upřednostňuje a zároveň PublicFrom, který označujeme atributem Column(Order=2)). Výsledek může překvapit:

 CREATE TABLE [Webinars] (
          [PublicFrom] datetime2 NOT NULL,
          [Id] int NOT NULL IDENTITY,
          [Title] nvarchar(max) NULL,
          [Price] decimal(14,2) NOT NULL,
          [DateFrom] datetime2 NOT NULL
          CONSTRAINT [PK_Webinars] PRIMARY KEY ([Id])
      );

Pořadí je tedy: PublicFrom, Id, Title, Price. Tedy pravidla jsou taková, že:

  1. pokud je property označena s [Column(Order)], dostává výsostní přednost bez ohledu na číslo v Order
  2. dále má přednost vždy property, která je klíč
  3. nakonec jdou ostatní properties s pořadím deklarovaným ve třídě

Použití v praxi

Pokud chci pořadí řešit a v třídě někde použiju [Column(Order)], pak si rovnou nastavím vždy pořadí i pro klíč, abych ho měl hned na začátku. Prioritu nastavím jen u sloupců, které chci skutečně vidět první. Zbytek neřeším.