yapı iskelesi (Tersine Mühendislik)

Tersine mühendislik, varlık türü sınıflarını ve veritabanı şemasını temel alan bir DbContext sınıfın iskelesini oluşturma işlemidir. EF Core Paket Yöneticisi Konsolu (PMC) araçlarının Scaffold-DbContext komutu veya .NET Komut Satırı Arabirimi (CLI) araçlarının dotnet ef dbcontext scaffold komutu kullanılarak gerçekleştirilebilir.

Not

Burada belgelenen ve DbContext varlık türlerinin iskelesi, visual studio kullanarak ASP.NET Core'daki denetleyicilerin iskelesinden farklıdır ve burada belgelenmemiştir.

İpucu

Visual Studio kullanıyorsanız EF Core Power Tools topluluk uzantısını deneyin. Bu araçlar, EF Core komut satırı araçlarının üzerine inşa edilen ve ek iş akışı ve özelleştirme seçenekleri sunan bir grafik aracı sağlar.

Önkoşullar

Gerekli bağımsız değişkenler

Hem PMC hem de .NET CLI komutlarının iki gerekli bağımsız değişkeni vardır: veritabanına bağlantı dizesi ve kullanılacak EF Core veritabanı sağlayıcısı.

Connection string

Komutun ilk bağımsız değişkeni, veritabanına bir bağlantı dizesidir. Araçlar, veritabanı şemasını okumak için bu bağlantı dizesini kullanır.

bağlantı dizesi nasıl alıntı yaptığınız ve kaçtığınız, komutu yürütmek için hangi kabuğu kullandığınıza bağlıdır; daha fazla bilgi için kabuğunuzun belgelerine bakın. Örneğin, PowerShell $ karakterine kaçış uygulamanızı gerektirir, ancak \ bunu gerektirmez.

Aşağıdaki örnek, varlık türlerini ve makinenin SQL Server LocalDB örneğinde bulunan veritabanından veritabanı sağlayıcısını kullanan bir DbContextChinook yapı iskelesi Microsoft.EntityFrameworkCore.SqlServer oluşturur.

dotnet ef dbcontext scaffold "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook" Microsoft.EntityFrameworkCore.SqlServer

bağlantı dizesi için kullanıcı gizli dizileri

ASP.NET Core projesi gibi barındırma modelini ve yapılandırma sistemini kullanan bir .NET uygulamanız varsa yapılandırmadan bağlantı dizesini okumak için Name=<connection-string> sözdizimini kullanabilirsiniz.

Örneğin, aşağıdaki yapılandırma dosyasına sahip bir ASP.NET Core uygulaması düşünün:

{
  "ConnectionStrings": {
    "Chinook": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=Chinook"
  }
}

Yapılandırma dosyasındaki bu bağlantı dizesi aşağıdakiler kullanılarak bir veritabanından iskele oluşturmak için kullanılabilir:

dotnet ef dbcontext scaffold "Name=ConnectionStrings:Chinook" Microsoft.EntityFrameworkCore.SqlServer

Ancak, bağlantı dizesi yapılandırma dosyalarında depolamak iyi bir fikir değildir, çünkü kaynak denetimine göndererek bunları yanlışlıkla kullanıma sunmaları çok kolaydır. Bunun yerine bağlantı dizesi, Azure Key Vault'un kullanılması veya yerel olarak çalışırken Gizli Dizi Yöneticisi aracının (diğer adıyla "Kullanıcı Gizli Dizileri") güvenli bir şekilde depolanması gerekir.

Örneğin, Kullanıcı Gizli Dizilerini kullanmak için önce bağlantı dizesi ASP.NET Core yapılandırma dosyanızdan kaldırın. Ardından, ASP.NET Core projesiyle aynı dizinde aşağıdaki komutu yürüterek Kullanıcı Gizli Dizilerini başlatın:

dotnet user-secrets init

Bu komut, bilgisayarınızda kaynak kodunuzdan ayrı bir depolama alanı ayarlar ve bu depolama için projeye bir anahtar ekler.

Ardından, bağlantı dizesi kullanıcı gizli dizilerinde depolayın. Örneğin:

dotnet user-secrets set ConnectionStrings:Chinook "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook"

Bundan önce yapılandırma dosyasından adlandırılmış bağlantı dizesi kullanan komut, bunun yerine Kullanıcı Gizli Dizileri'nde depolanan bağlantı dizesi kullanır. Örneğin:

dotnet ef dbcontext scaffold "Name=ConnectionStrings:Chinook" Microsoft.EntityFrameworkCore.SqlServer

yapı iskelesi kodda Bağlan ion dizeleri

Varsayılan olarak, yapı iskelesi, yapı iskelesi kodunda bağlantı dizesi içerir, ancak bir uyarı içerir. Örneğin:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
    => optionsBuilder.UseSqlServer("Data Source=(LocalDb)\\MSSQLLocalDB;Database=AllTogetherNow");

Bu, oluşturulan kodun ilk kullanıldığında kilitlenmemesi için yapılır ve bu çok kötü bir öğrenme deneyimi olacaktır. Ancak uyarının dediği gibi bağlantı dizesi üretim kodunda bulunmamalıdır. bağlantı dizesi yönetilebileceği çeşitli yollar için bkz. DbContext Yaşam Süresi, Yapılandırma ve Başlatma.

İpucu

-NoOnConfiguring bağlantı dizesi içeren yöntemin OnConfiguring oluşturulmasını engellemek için (Visual Studio PMC) veya --no-onconfiguring (.NET CLI) seçeneği geçirilebilir.

Sağlayıcı adı

İkinci bağımsız değişken, sağlayıcı adıdır. Sağlayıcı adı, genellikle sağlayıcının NuGet paket adıyla aynıdır. Örneğin, SQL Server veya Azure SQL için kullanın Microsoft.EntityFrameworkCore.SqlServer.

Komut satırı seçenekleri

yapı iskelesi işlemi çeşitli komut satırı seçenekleriyle denetlenebilir.

Tabloları ve görünümleri belirtme

Varsayılan olarak, veritabanı şemasındaki tüm tablolar ve görünümler varlık türlerine iskelesi oluşturulur. Şemaları ve tabloları belirterek hangi tabloların ve görünümlerin yapı iskelesi kurulacağını sınırlayabilirsiniz.

-Schemas (Visual Studio PMC) veya --schema (.NET CLI) bağımsız değişkeni, varlık türlerinin oluşturulacağı tablo ve görünümlerin şemalarını belirtir. Bu bağımsız değişken atlanırsa, tüm şemalar eklenir. Bu seçenek kullanılırsa, veya --tablekullanılarak -Tables açıkça dahil edilmeseler bile şemalardaki tüm tablolar ve görünümler modele dahil edilir.

Varlık türlerinin -Tables oluşturulacağı tabloları ve görünümleri (Visual Studio PMC) veya --table (.NET CLI) bağımsız değişkeni belirtti. Belirli bir şemadaki tablolar veya görünümler 'schema.table' veya 'schema.view' biçimi kullanılarak eklenebilir. Bu seçenek atlanırsa, tüm tablolar ve görünümler eklenir. |

Örneğin, yalnızca ve Albums tablolarının iskelesini Artists yapmak için:

dotnet ef dbcontext scaffold ... --table Artist --table Album

ve Contractor şemalarından tüm tablo ve görünümlerin iskelesini Customer yapmak için:

dotnet ef dbcontext scaffold ... --schema Customer --schema Contractor

Örneğin, tabloyu şemadan ve ve Contracts tablolarını şemadan ContractorAccounts iskeleye Purchases almak Customer için:

dotnet ef dbcontext scaffold ... --table Customer.Purchases --table Contractor.Accounts --table Contractor.Contracts

Veritabanı adlarını koruma

Tablo ve sütun adları, tür ve özellikler için, varsayılan olarak .NET adlandırma kurallarıyla daha iyi eşleşecek şekilde düzeltilir. (Visual Studio PMC) veya --use-database-names (.NET CLI) belirtilmesi -UseDatabaseNames , özgün veritabanı adlarını olabildiğince koruyarak bu davranışı devre dışı bırakır. Geçersiz .NET tanımlayıcıları düzeltilmeye devam eder ve gezinti özellikleri gibi sentezlenmiş adlar .NET adlandırma kurallarına uymaya devam eder.

Örneğin, aşağıdaki tabloları göz önünde bulundurun:

CREATE TABLE [BLOGS] (
    [ID] int NOT NULL IDENTITY,
    [Blog_Name] nvarchar(max) NOT NULL,
    CONSTRAINT [PK_Blogs] PRIMARY KEY ([ID]));

CREATE TABLE [posts] (
    [id] int NOT NULL IDENTITY,
    [postTitle] nvarchar(max) NOT NULL,
    [post content] nvarchar(max) NOT NULL,
    [1 PublishedON] datetime2 NOT NULL,
    [2 DeletedON] datetime2 NULL,
    [BlogID] int NOT NULL,
    CONSTRAINT [PK_Posts] PRIMARY KEY ([id]),
    CONSTRAINT [FK_Posts_Blogs_BlogId] FOREIGN KEY ([BlogID]) REFERENCES [Blogs] ([ID]) ON DELETE CASCADE);

Varsayılan olarak, aşağıdaki varlık türleri bu tablolardan iskelesi oluşturulacaktır:

public partial class Blog
{
    public int Id { get; set; }
    public string BlogName { get; set; } = null!;
    public virtual ICollection<Post> Posts { get; set; } = new List<Post>();
}

public partial class Post
{
    public int Id { get; set; }
    public string PostTitle { get; set; } = null!;
    public string PostContent { get; set; } = null!;
    public DateTime _1PublishedOn { get; set; }
    public DateTime? _2DeletedOn { get; set; }
    public int BlogId { get; set; }
    public virtual Blog Blog { get; set; } = null!;
    public virtual ICollection<Tag> Tags { get; set; } = new List<Tag>();
}

Ancak, veya --use-database-names kullanarak -UseDatabaseNames aşağıdaki varlık türlerinin sonucunu elde edin:

public partial class BLOG
{
    public int ID { get; set; }
    public string Blog_Name { get; set; } = null!;
    public virtual ICollection<post> posts { get; set; } = new List<post>();
}

public partial class post
{
    public int id { get; set; }
    public string postTitle { get; set; } = null!;
    public string post_content { get; set; } = null!;
    public DateTime _1_PublishedON { get; set; }
    public DateTime? _2_DeletedON { get; set; }
    public int BlogID { get; set; }
    public virtual BLOG Blog { get; set; } = null!;
}

Eşleme özniteliklerini kullanma (diğer adıyla Veri Ek Açıklamaları)

Varlık türleri varsayılan olarak içindeki OnModelCreating API kullanılarak ModelBuilder yapılandırılır. Mümkün olduğunda eşleme özniteliklerini kullanmak için (PMC) veya --data-annotations (.NET Core CLI) belirtin -DataAnnotations .

Örneğin, Fluent API'sinin kullanılması şu yapı iskelesini oluşturur:

entity.Property(e => e.Title)
    .IsRequired()
    .HasMaxLength(160);

Veri Ek Açıklamaları kullanılırken bu yapı iskelesi oluşturulur:

[Required]
[StringLength(160)]
public string Title { get; set; }

İpucu

Modelin bazı yönleri eşleme öznitelikleri kullanılarak yapılandırılamaz. İskele, bu durumları işlemek için model oluşturma API'sini kullanmaya devam eder.

DbContext adı

yapı iskelesi oluşturulmuş DbContext sınıf adı, varsayılan olarak Bağlam ile birlikte gelen veritabanının adıdır. Farklı bir tane belirtmek için PMC'de -Context ve .NET Core CLI'da --context kullanın.

Hedef dizinler ve ad alanları

Varlık sınıfları ve DbContext sınıfı, projenin kök dizinine yapı iskelesi oluşturulur ve projenin varsayılan ad alanını kullanır.

--output-dir kullanarak sınıfların oluşturulduğu dizini belirtebilirsiniz ve --context-dir, DbContext sınıfını varlık türü sınıflarından ayrı bir dizine yapı iskelesi oluşturmak için kullanılabilir:

dotnet ef dbcontext scaffold ... --context-dir Data --output-dir Models

Varsayılan olarak, ad alanı, kök ad alanı ve projenin kök dizini altındaki alt dizinlerin adları olur. Ancak, kullanarak --namespacetüm çıkış sınıfları için ad alanını geçersiz kılabilirsiniz. Ayrıca --context-namespace kullanarak, yalnızca DbContext sınıfı için ad alanını geçersiz kılabilirsiniz:

dotnet ef dbcontext scaffold ... --namespace Your.Namespace --context-namespace Your.DbContext.Namespace

yapı iskelesi oluşturulmuş kod

Mevcut bir veritabanından yapı iskelesi oluşturmanın sonucu şudur:

  • öğesinden devralan bir sınıf içeren dosya DbContext
  • Her varlık türü için bir dosya

İpucu

EF7'den başlayarak, oluşturulan kodu özelleştirmek için T4 metin şablonlarını da kullanabilirsiniz. Daha fazla ayrıntı için bkz. Özel Tersine Mühendislik Şablonları.

C# Null atanabilir başvuru türleri

İskele, C# null atanabilir başvuru türlerini (NTS) kullanan EF modeli ve varlık türleri oluşturabilir. NRT kullanımı, kodun iskelesinin oluşturulduğu C# projesinde NRT desteği etkinleştirildiğinde otomatik olarak iskelelenir.

Örneğin, aşağıdaki Tags tabloda hem null değer atanabilir hem de boş değer atanamayan dize sütunları yer alır:

CREATE TABLE [Tags] (
  [Id] int NOT NULL IDENTITY,
  [Name] nvarchar(max) NOT NULL,
  [Description] nvarchar(max) NULL,
  CONSTRAINT [PK_Tags] PRIMARY KEY ([Id]));

Bu, oluşturulan sınıfta karşılık gelen null atanabilir ve null atanamaz dize özelliklerine neden olur:

public partial class Tag
{
    public Tag()
    {
        Posts = new HashSet<Post>();
    }

    public int Id { get; set; }
    public string Name { get; set; } = null!;
    public string? Description { get; set; }

    public virtual ICollection<Post> Posts { get; set; }
}

Benzer şekilde, aşağıdaki Posts tablolar tabloyla Blogs gerekli bir ilişki içerir:

CREATE TABLE [Posts] (
    [Id] int NOT NULL IDENTITY,
    [Title] nvarchar(max) NOT NULL,
    [Contents] nvarchar(max) NOT NULL,
    [PostedOn] datetime2 NOT NULL,
    [UpdatedOn] datetime2 NULL,
    [BlogId] int NOT NULL,
    CONSTRAINT [PK_Posts] PRIMARY KEY ([Id]),
    CONSTRAINT [FK_Posts_Blogs_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [Blogs] ([Id]));

Bu, bloglar arasındaki null atanamaz (gerekli) ilişkinin iskelesini oluşturur:

public partial class Blog
{
    public Blog()
    {
        Posts = new HashSet<Post>();
    }

    public int Id { get; set; }
    public string Name { get; set; } = null!;

    public virtual ICollection<Post> Posts { get; set; }
}

Ve gönderiler:

public partial class Post
{
    public Post()
    {
        Tags = new HashSet<Tag>();
    }

    public int Id { get; set; }
    public string Title { get; set; } = null!;
    public string Contents { get; set; } = null!;
    public DateTime PostedOn { get; set; }
    public DateTime? UpdatedOn { get; set; }
    public int BlogId { get; set; }

    public virtual Blog Blog { get; set; } = null!;

    public virtual ICollection<Tag> Tags { get; set; }
}

Çoka çok ilişkiler

yapı iskelesi işlemi basit birleştirme tablolarını algılar ve bunlar için otomatik olarak çoka çok eşleme oluşturur. Örneğin, ve tablolarını Posts ve Tagsbunları bağlayan birleştirme tablosunu PostTag göz önünde bulundurun:

CREATE TABLE [Tags] (
  [Id] int NOT NULL IDENTITY,
  [Name] nvarchar(max) NOT NULL,
  [Description] nvarchar(max) NULL,
  CONSTRAINT [PK_Tags] PRIMARY KEY ([Id]));

CREATE TABLE [Posts] (
    [Id] int NOT NULL IDENTITY,
    [Title] nvarchar(max) NOT NULL,
    [Contents] nvarchar(max) NOT NULL,
    [PostedOn] datetime2 NOT NULL,
    [UpdatedOn] datetime2 NULL,
    CONSTRAINT [PK_Posts] PRIMARY KEY ([Id]));

CREATE TABLE [PostTag] (
    [PostsId] int NOT NULL,
    [TagsId] int NOT NULL,
    CONSTRAINT [PK_PostTag] PRIMARY KEY ([PostsId], [TagsId]),
    CONSTRAINT [FK_PostTag_Posts_TagsId] FOREIGN KEY ([TagsId]) REFERENCES [Tags] ([Id]) ON DELETE CASCADE,
    CONSTRAINT [FK_PostTag_Tags_PostsId] FOREIGN KEY ([PostsId]) REFERENCES [Posts] ([Id]) ON DELETE CASCADE);

yapı iskelesi yapıldığında, bu durum Post için bir sınıfa neden olur:

public partial class Post
{
    public Post()
    {
        Tags = new HashSet<Tag>();
    }

    public int Id { get; set; }
    public string Title { get; set; } = null!;
    public string Contents { get; set; } = null!;
    public DateTime PostedOn { get; set; }
    public DateTime? UpdatedOn { get; set; }
    public int BlogId { get; set; }

    public virtual Blog Blog { get; set; } = null!;

    public virtual ICollection<Tag> Tags { get; set; }
}

Tag için de bir sınıf:

public partial class Tag
{
    public Tag()
    {
        Posts = new HashSet<Post>();
    }

    public int Id { get; set; }
    public string Name { get; set; } = null!;
    public string? Description { get; set; }

    public virtual ICollection<Post> Posts { get; set; }
}

Ama tablo için PostTag sınıf yok. Bunun yerine, çoka çok ilişkisi için yapılandırma yapı iskelesi oluşturulur:

entity.HasMany(d => d.Tags)
    .WithMany(p => p.Posts)
    .UsingEntity<Dictionary<string, object>>(
        "PostTag",
        l => l.HasOne<Tag>().WithMany().HasForeignKey("PostsId"),
        r => r.HasOne<Post>().WithMany().HasForeignKey("TagsId"),
        j =>
            {
                j.HasKey("PostsId", "TagsId");
                j.ToTable("PostTag");
                j.HasIndex(new[] { "TagsId" }, "IX_PostTag_TagsId");
            });

Diğer programlama dilleri

Microsoft tarafından yayımlanan EF Core paketleri C# kodunun iskelesini oluşturur. Ancak, temel yapı iskelesi sistemi diğer dillere iskele oluşturmak için bir eklenti modelini destekler. Bu eklenti modeli, topluluk tarafından çalıştırılan çeşitli projeler tarafından kullanılır, örneğin:

Kodu özelleştirme

EF7'den başlayarak, oluşturulan kodu özelleştirmenin en iyi yollarından biri, kodu oluşturmak için kullanılan T4 şablonlarını özelleştirmektir.

Kod oluşturulduktan sonra da değiştirilebilir, ancak bunu yapmak için en iyi yol, veritabanı modeli değiştiğinde iskele işlemini yeniden çalıştırmayı isteyip istemediğinize bağlıdır.

yapı iskelesi yalnızca bir kez

Bu yaklaşımla, yapı iskelesi oluşturulmuş kod, ileride kod tabanlı eşleme için bir başlangıç noktası sağlar. Oluşturulan kodda herhangi bir değişiklik istendiği gibi yapılabilir; projenizdeki diğer kodlarda olduğu gibi normal bir kod haline gelir.

Veritabanını ve EF modelini eşitlenmiş durumda tutmak iki yoldan biriyle yapılabilir:

  • EF Core veritabanı geçişlerini kullanmaya geçin ve şemayı yönlendirmek için geçişleri kullanarak varlık türlerini ve EF modeli yapılandırmasını gerçeklerin kaynağı olarak kullanın.
  • Veritabanı değiştiğinde varlık türlerini ve EF yapılandırmasını el ile güncelleştirin. Örneğin, tabloya yeni bir sütun eklenirse, eşlenen varlık türüne sütun için bir özellik ekleyin ve içindeki eşleme özniteliklerini ve/veya kodu OnModelCreatingkullanarak gerekli yapılandırmaları ekleyin. Bu oldukça kolaydır ve tek gerçek zorluk, veritabanı değişikliklerinin bir şekilde kaydedildiğinden veya algılandığından emin olmak ve koddan sorumlu geliştiricilerin tepki gösterebilmesini sağlamaktır.

Yinelenen yapı iskelesi

Bir kez yapı iskelesi oluşturmanın alternatif bir yaklaşımı, veritabanı her değiştiğinde yeniden iskele oluşturmaktır. Bu, daha önce yapı iskelesi oluşturulmuş tüm kodların üzerine yazılır ; yani bu koddaki varlık türlerinde veya EF yapılandırmasında yapılan tüm değişiklikler kaybolur.

[İPUCU] Varsayılan olarak, EF komutları yanlışlıkla kod kaybına karşı korumak için mevcut kodun üzerine yazmaz. -Force Mevcut dosyaların üzerine yazmaya zorlamak için (Visual Studio PMC) veya --force (.NET CLI) bağımsız değişkeni kullanılabilir.

yapı iskelesi oluşturulmuş kodun üzerine yazılacağından, doğrudan değiştirmemek, bunun yerine kısmi sınıflara ve yöntemlere ve EF Core'da yapılandırmanın geçersiz kılınmasına izin veren mekanizmalara güvenmek en iyisidir. Özellikle:

  • DbContext Hem sınıf hem de varlık sınıfları kısmi olarak oluşturulur. Bu, yapı iskelesi çalıştırıldığında geçersiz kılınmayacak ayrı bir dosyaya ek üyeler ve kodlar eklenmesine olanak tanır.
  • DbContext sınıfı adlı OnModelCreatingPartialkısmi bir yöntem içerir. Bu yöntemin bir uygulaması için kısmi sınıfa DbContexteklenebilir. Daha sonra çağrıldıktan sonra OnModelCreating çağrılır.
  • API'ler kullanılarak ModelBuilder yapılan model yapılandırması, kurallar veya eşleme öznitelikleri tarafından yapılan tüm yapılandırmaların yanı sıra model oluşturucuda yapılan daha önceki yapılandırmaları geçersiz kılar. Bu, içindeki kodun OnModelCreatingPartial , yapılandırmayı kaldırmaya gerek kalmadan iskele işlemi tarafından oluşturulan yapılandırmayı geçersiz kılmak için kullanılabileceğini gösterir.

Son olarak, EF7'den başlayarak kod oluşturmak için kullanılan T4 şablonlarının özelleştirilebileceğini unutmayın. Bu genellikle varsayılanlarla yapı iskelesi oluşturmaktan ve ardından kısmi sınıflarla ve/veya yöntemlerle değiştirmekten daha etkili bir yaklaşımdır.

Nasıl çalışır?

Tersine mühendislik, veritabanı şemasını okuyarak başlar. Tablolar, sütunlar, kısıtlamalar ve dizinler hakkındaki bilgileri okur.

Ardından, bir EF Core modeli oluşturmak için şema bilgilerini kullanır. Tablolar varlık türleri oluşturmak için, sütunlar özellik oluşturmak için ve yabancı anahtarlar ilişki oluşturmak için kullanılır.

Son olarak, model, kod oluşturmak için kullanılır. Uygulamanızdan aynı modeli yeniden oluşturmak için ilgili varlık türü sınıfları, Fluent API'lere ve veri ek açıklamalarına yapı iskelesi oluşturulur.

Sınırlamalar

  • Bir modelle ilgili her şey, bir veritabanı şeması kullanılarak temsil edilemez. Örneğin, devralma hiyerarşileri, sahip olunan türler ve tablo bölme hakkındaki bilgiler veritabanı şemasında mevcut değildir. Bu nedenle, bu yapılar hiçbir zaman yapı iskelesi kurulmayacak.
  • Ayrıca, bazı sütun türleri EF Core sağlayıcısı tarafından desteklenmeyebilir. Bu sütunlar modele dahil edilmeyecektir.
  • İki kullanıcının aynı varlığı aynı anda güncelleştirmesini önlemek için EF Core modelinde eşzamanlılık belirteçleri tanımlayabilirsiniz. Bazı veritabanlarında bu tür bir sütunu (örneğin, SQL Server'da rowversion) temsil eden özel bir tür vardır; bu durumda bu bilgileri tersine çevirebiliriz; ancak, diğer eşzamanlılık belirteçleri yapı iskelesi yapılmaz.