Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
EF Core, varlık türlerini veritabanındaki tablolara eşleme konusunda çok fazla esneklik sunar. EF tarafından oluşturulmamış bir veritabanı kullanmanız gerektiğinde bu daha da kullanışlı hale gelir.
Aşağıdaki teknikler tablolar açısından açıklanmıştır, ancak görünümlere eşlenirken de aynı sonuç elde edilebilir.
Tablo bölme
EF Core, iki veya daha fazla varlığı tek bir satıra eşlemeye olanak tanır. Buna tablo bölme veya tablo paylaşımı denir.
Konfigürasyon
Varlık türlerini bölen tabloyu kullanmak için, birincil anahtarların aynı tabloya eşlenmesi ve aynı tablodaki bir varlık türünün birincil anahtarı ile diğerinin arasında en az bir ilişkinin yapılandırılması gerekir.
Tablo bölmeye yönelik yaygın bir senaryo, daha yüksek performans veya kapsülleme için tablodaki sütunların yalnızca bir alt kümesini kullanmaktır.
Bu örnekte Order
, öğesinin DetailedOrder
bir alt kümesini temsil eder.
public class Order
{
public int Id { get; set; }
public OrderStatus? Status { get; set; }
public DetailedOrder DetailedOrder { get; set; }
}
public class DetailedOrder
{
public int Id { get; set; }
public OrderStatus? Status { get; set; }
public string BillingAddress { get; set; }
public string ShippingAddress { get; set; }
public byte[] Version { get; set; }
}
Gerekli yapılandırmaya ek olarak, Property(o => o.Status).HasColumnName("Status")
çağırarak DetailedOrder.Status
ve Order.Status
'yi aynı sütuna eşliyoruz.
modelBuilder.Entity<DetailedOrder>(
dob =>
{
dob.ToTable("Orders");
dob.Property(o => o.Status).HasColumnName("Status");
});
modelBuilder.Entity<Order>(
ob =>
{
ob.ToTable("Orders");
ob.Property(o => o.Status).HasColumnName("Status");
ob.HasOne(o => o.DetailedOrder).WithOne()
.HasForeignKey<DetailedOrder>(o => o.Id);
ob.Navigation(o => o.DetailedOrder).IsRequired();
});
Tavsiye
Daha fazla bağlam için örnek projenin tamamına bakın.
Kullanım
Tablo bölme kullanarak varlıkları kaydetme ve sorgulama işlemi diğer varlıklarla aynı şekilde yapılır:
using (var context = new TableSplittingContext())
{
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();
context.Add(
new Order
{
Status = OrderStatus.Pending,
DetailedOrder = new DetailedOrder
{
Status = OrderStatus.Pending,
ShippingAddress = "221 B Baker St, London",
BillingAddress = "11 Wall Street, New York"
}
});
await context.SaveChangesAsync();
}
using (var context = new TableSplittingContext())
{
var pendingCount = await context.Orders.CountAsync(o => o.Status == OrderStatus.Pending);
Console.WriteLine($"Current number of pending orders: {pendingCount}");
}
using (var context = new TableSplittingContext())
{
var order = await context.DetailedOrders.FirstAsync(o => o.Status == OrderStatus.Pending);
Console.WriteLine($"First pending order will ship to: {order.ShippingAddress}");
}
İsteğe bağlı bağımlı varlık
Bağımlı varlık NULL
tarafından kullanılan tüm sütunlar veritabanındaysa sorgulandığında bunun örneği oluşturulmaz. Bu, asıl öğedeki ilişki özelliğinin null olacağı isteğe bağlı bir bağımlı varlığı modellemeye olanak tanır. Bu durum, bağımlının tüm özellikleri isteğe bağlıysa ve null
olarak ayarlandıysa da gerçekleşebilir; bunun beklenmeyen bir durum olabileceğine dikkat edin.
Ancak, ek denetim sorgu performansını etkileyebilir. Ayrıca, bağımlı varlık türünün kendi bağımlıları varsa, bir örneğin oluşturulup oluşturulmayacağını belirlemek önemsiz hale gelir. Bu sorunlardan kaçınmak için bağımlı varlık türü gerekli olarak işaretlenebilir, daha fazla bilgi için bkz. Gerekli olarak işaretlenen bire bir bağımlı varlık türleri.
Eşzamanlılık belirteçleri
Tabloyu paylaşan varlık türlerinden herhangi birinin eşzamanlılık belirteci varsa, diğer tüm varlık türlerine de dahil edilmelidir. Aynı tabloya eşlenen varlıklardan yalnızca biri güncelleştirildiğinde eski eşzamanlılık belirteci değerini önlemek için bu gereklidir.
Eşzamanlılık belirtecinin tüketen koda açık olmasını önlemek için gölge özellik olarak bir tane oluşturmak mümkündür:
modelBuilder.Entity<Order>()
.Property<byte[]>("Version").IsRowVersion().HasColumnName("Version");
modelBuilder.Entity<DetailedOrder>()
.Property(o => o.Version).IsRowVersion().HasColumnName("Version");
Miras
Bu bölüme devam etmeden önce devralmayla ilgili ayrılmış sayfanın okunmasını öneririz.
Tablo bölme kullanan bağımlı türlerin devralma hiyerarşisi olabilir, ancak bazı sınırlamalar vardır:
- Türetilmiş türler aynı tabloyla eşlenemeyeceğinden bağımlı varlık türü TPC eşlemesini kullanamaz.
- Bağımlı varlık türü TPT eşlemesini kullanabilir , ancak yalnızca kök varlık türü tablo bölmeyi kullanabilir.
- Asıl varlık türü TPC kullanıyorsa, yalnızca alt öğeleri olmayan varlık türleri tablo bölmeyi kullanabilir. Aksi takdirde, bağımlı sütunların türetilmiş türlere karşılık gelen tablolarda çoğaltılması ve tüm etkileşimleri karmaşık hale getirmesi gerekir.
Varlık bölme
EF Core, bir varlığı iki veya daha fazla tablodaki satırlarla eşlemeye olanak tanır. Buna varlık bölme adı verilir.
Konfigürasyon
Örneğin, müşteri verilerini barındıran üç tablo içeren bir veritabanı düşünün:
-
Customers
Müşteri bilgileri tablosu -
PhoneNumbers
Müşterinin telefon numarası için bir tablo -
Addresses
Müşterinin adresi için bir tablo
SQL Server'da bu tabloların tanımları şunlardır:
CREATE TABLE [Customers] (
[Id] int NOT NULL IDENTITY,
[Name] nvarchar(max) NOT NULL,
CONSTRAINT [PK_Customers] PRIMARY KEY ([Id])
);
CREATE TABLE [PhoneNumbers] (
[CustomerId] int NOT NULL,
[PhoneNumber] nvarchar(max) NULL,
CONSTRAINT [PK_PhoneNumbers] PRIMARY KEY ([CustomerId]),
CONSTRAINT [FK_PhoneNumbers_Customers_CustomerId] FOREIGN KEY ([CustomerId]) REFERENCES [Customers] ([Id]) ON DELETE CASCADE
);
CREATE TABLE [Addresses] (
[CustomerId] int NOT NULL,
[Street] nvarchar(max) NOT NULL,
[City] nvarchar(max) NOT NULL,
[PostCode] nvarchar(max) NULL,
[Country] nvarchar(max) NOT NULL,
CONSTRAINT [PK_Addresses] PRIMARY KEY ([CustomerId]),
CONSTRAINT [FK_Addresses_Customers_CustomerId] FOREIGN KEY ([CustomerId]) REFERENCES [Customers] ([Id]) ON DELETE CASCADE
);
Bu tabloların her biri genellikle türler arasındaki ilişkilerle kendi varlık türlerine eşlenir. Ancak, üç tablonun hepsi her zaman birlikte kullanılıyorsa, bunların tümünü tek bir varlık türüne eşlemek daha kullanışlı olabilir. Örneğin:
public class Customer
{
public Customer(string name, string street, string city, string? postCode, string country)
{
Name = name;
Street = street;
City = city;
PostCode = postCode;
Country = country;
}
public int Id { get; set; }
public string Name { get; set; }
public string? PhoneNumber { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string? PostCode { get; set; }
public string Country { get; set; }
}
Bu, EF7'de varlık türündeki her bölme için SplitToTable
çağrılarak sağlanır. Örneğin, aşağıdaki kod Customer
varlık türünü yukarıda gösterilen Customers
, PhoneNumbers
ve Addresses
tablolarına böler.
modelBuilder.Entity<Customer>(
entityBuilder =>
{
entityBuilder
.ToTable("Customers")
.SplitToTable(
"PhoneNumbers",
tableBuilder =>
{
tableBuilder.Property(customer => customer.Id).HasColumnName("CustomerId");
tableBuilder.Property(customer => customer.PhoneNumber);
})
.SplitToTable(
"Addresses",
tableBuilder =>
{
tableBuilder.Property(customer => customer.Id).HasColumnName("CustomerId");
tableBuilder.Property(customer => customer.Street);
tableBuilder.Property(customer => customer.City);
tableBuilder.Property(customer => customer.PostCode);
tableBuilder.Property(customer => customer.Country);
});
});
Ayrıca, gerekirse tabloların her biri için farklı sütun adlarının belirtilebildiğine de dikkat edin. Ana tablonun sütun adını yapılandırmak için bkz. Tabloya özgü model yapılandırması.
Bağlama yabancı anahtarını yapılandırma
Eşlenen tabloları bağlayan FK, bildirildiği özelliklerin aynısını hedefler. Normalde, yedekli olacağından veritabanında oluşturulmaz. Ancak varlık türünün birden fazla tabloyla eşlenmesi için bir özel durum vardır. Fasetlerini değiştirmek için ilişki yapılandırmasını Fluent API kullanabilirsiniz:
modelBuilder.Entity<Customer>()
.HasOne<Customer>()
.WithOne()
.HasForeignKey<Customer>(a => a.Id)
.OnDelete(DeleteBehavior.Restrict);
Sınırlamalar
- Varlık bölme hiyerarşilerindeki varlık türleri için kullanılamaz.
- Ana tablodaki herhangi bir satır için, bölünmüş tabloların her birinde bir satır olmalıdır (parçalar isteğe bağlı değildir).
Tabloya özgü faset yapılandırması
Bazı eşleme desenleri, aynı CLR özelliğinin birden çok farklı tablonun her birindeki bir sütuna eşlenmesine neden olur. EF7, bu sütunların farklı adlara sahip olmasını sağlar. Örneğin, basit bir devralma hiyerarşisini göz önünde bulundurun:
public abstract class Animal
{
public int Id { get; set; }
public string Breed { get; set; } = null!;
}
public class Cat : Animal
{
public string? EducationalLevel { get; set; }
}
public class Dog : Animal
{
public string? FavoriteToy { get; set; }
}
TPT devralma eşleme stratejisiyle bu türler üç tabloya eşlenir. Ancak, her tablodaki anahtar sütunu farklı bir adı olabilir. Örneğin:
CREATE TABLE [Animals] (
[Id] int NOT NULL IDENTITY,
[Breed] nvarchar(max) NOT NULL,
CONSTRAINT [PK_Animals] PRIMARY KEY ([Id])
);
CREATE TABLE [Cats] (
[CatId] int NOT NULL,
[EducationalLevel] nvarchar(max) NULL,
CONSTRAINT [PK_Cats] PRIMARY KEY ([CatId]),
CONSTRAINT [FK_Cats_Animals_CatId] FOREIGN KEY ([CatId]) REFERENCES [Animals] ([Id]) ON DELETE CASCADE
);
CREATE TABLE [Dogs] (
[DogId] int NOT NULL,
[FavoriteToy] nvarchar(max) NULL,
CONSTRAINT [PK_Dogs] PRIMARY KEY ([DogId]),
CONSTRAINT [FK_Dogs_Animals_DogId] FOREIGN KEY ([DogId]) REFERENCES [Animals] ([Id]) ON DELETE CASCADE
);
EF7, bu eşlemenin iç içe tablo oluşturucusu kullanılarak yapılandırılmasına izin verir:
modelBuilder.Entity<Animal>().ToTable("Animals");
modelBuilder.Entity<Cat>()
.ToTable(
"Cats",
tableBuilder => tableBuilder.Property(cat => cat.Id).HasColumnName("CatId"));
modelBuilder.Entity<Dog>()
.ToTable(
"Dogs",
tableBuilder => tableBuilder.Property(dog => dog.Id).HasColumnName("DogId"));
TPC devralma eşlemesi ile Breed
özelliği, farklı tablolardaki farklı sütun adlarına da eşlenebilir. Örneğin, aşağıdaki TPC tablolarını göz önünde bulundurun:
CREATE TABLE [Cats] (
[CatId] int NOT NULL DEFAULT (NEXT VALUE FOR [AnimalSequence]),
[CatBreed] nvarchar(max) NOT NULL,
[EducationalLevel] nvarchar(max) NULL,
CONSTRAINT [PK_Cats] PRIMARY KEY ([CatId])
);
CREATE TABLE [Dogs] (
[DogId] int NOT NULL DEFAULT (NEXT VALUE FOR [AnimalSequence]),
[DogBreed] nvarchar(max) NOT NULL,
[FavoriteToy] nvarchar(max) NULL,
CONSTRAINT [PK_Dogs] PRIMARY KEY ([DogId])
);
EF7 şu tablo eşlemesini destekler:
modelBuilder.Entity<Animal>().UseTpcMappingStrategy();
modelBuilder.Entity<Cat>()
.ToTable(
"Cats",
builder =>
{
builder.Property(cat => cat.Id).HasColumnName("CatId");
builder.Property(cat => cat.Breed).HasColumnName("CatBreed");
});
modelBuilder.Entity<Dog>()
.ToTable(
"Dogs",
builder =>
{
builder.Property(dog => dog.Id).HasColumnName("DogId");
builder.Property(dog => dog.Breed).HasColumnName("DogBreed");
});