Bu hata, EF varlığınız için pk'yi çözemediğinde oluşur. Çoğu durumda basit varlıklar için EF kuralları pk'yi çalıştırabilir, ancak sizin durumunuzda bileşik bir anahtar kullanıyorsunuz, bu nedenle bunun yapılandırılması gerekiyor. Varlıklarınızı nasıl haritaladığınıza bağlı olarak bunu şu adresten yapabilirsiniz::
- bir EDMX
- DbContext içinde.Onmodel Oluşturma
- bir kullanarak
EntityTypeConfiguration
bildiri
- varlığın kendi içindeki öznitelikleri kullanma
Varlıklarınızın nasıl yapılandırıldığını bilmediğimizden, varlığınızdaki öznitelik yaklaşımını test olarak kullanarak bunu neden olarak doğrulayabilirsiniz. Bir EDMX kullanıyorsanız, varlık sınıfları oluşturulur, böylece bunu EDMX içindeki yapılandırmayla değiştirmek istersiniz. (Sana gerçekten yardım edemem çünkü lanet şeyleri kullanmıyorum: D )
Muhtemelen böyle bir şeye sahip olacaksınız:
public class CarRentalFields
{
[Column("start_day")]
public DateTime StartDay { get; set; }
[Column("return_date")]
public DateTime ReturnDate { get; set; }
[Column("user_id")]
public int UserId { get; set; }
[Column("car_number")]
public DateTime CarNumber { get; set; }
// ... more columns...
}
Hatta bir tane bile olabilir [Key]
CarNumber gibi bu alanlardan birinde öznitelik. Varlıkta eşlenen bir PK varsa, sorun, satırı benzersiz olarak tanımlayacak kadar spesifik olmamasıdır. EF bir varlığı güncelleştirmeye gittiğinde, denetliyor ve tablodaki yalnızca bir satırı güncelleştirmeyi bekliyor. Birden fazla satırın etkileneceğini buluyor, bu yüzden başarısız oluyor.
İçin öznitelikleri ekleme [Key]
sütun sırası ile bileşik anahtar olarak tanınır.
public class CarRentalFields
{
[Key, Column(Name="start_day", Order=1)]
public DateTime StartDay { get; set; }
[Key, Column(Name="return_date", Order=2)]
public DateTime ReturnDate { get; set; }
[Key, Column(Name="user_id", Order=3)]
public int UserId { get; set; }
[Key, Column(Name="car_number", Order=4)]
public DateTime CarNumber { get; set; }
// ... more columns...
}
Bu 4 sütunun tabloda benzersiz bir kısıtlama olması garanti edilirse, EF, UPDATE SQL deyimini oluştururken yalnızca bir satır güncellendiğinde tatmin olur.
Bu işe yararsa ve bir EDMX kullanıyorsanız, bu varlık sınıfı yeniden oluşturulabileceğinden, ek özniteliklerinizi kaybederek uygun değişiklikleri yapmak için EDMX eşlemenizi gözden geçirmeniz ve değiştirmeniz gerekeceğini tekrar unutmayın. (Bir edmx'ten oluşturulan varlık sınıflarının, oluşturulan bir sınıf olduğu konusunda sizi uyaran bir yorum başlığına sahip olduğuna inanıyorum, bu nedenle dikkat edilmesi gereken bir göstergedir.)
Güncelleme:
Bu konudaki birincil şüphelim, tablonun aslında farklı bir PK kombinasyonu çalıştıran veya bu alanların niteliği göz önüne alındığında daha büyük olasılıkla PK olmayan eşleşen bir PK tanımına sahip olmaması olacaktır. EF, PK tanımlı olmayan tablolarda çalışabilir, ancak kayıtların benzersiz olarak tanımlanabilmesini sağlayan bir Anahtar tanımı gerektirir. Gördüğünüz hata, bu anahtar tanımı yeterince benzersiz olmadığında gerçekleşir. (Yani, araç 1'i güncelliyorsanız ve sahip olduğunuz satırı seçiyorsanız:
car_number = 1, start_day = 2021-11-21, return_day = 2021-11-22, user_id = 0 Sorun, birden fazla satırın db'de bu kombinasyona sahip olmasıdır. Denetlediğiniz db'nin birden fazla eşleşen satırı yoksa, uygulamanız neredeyse kesinlikle denetlediğinizden farklı bir veritabanına işaret ediyor demektir.
Bunu doğrulamak için yapabileceğiniz şeyler:
- çalışma zamanı bağlantı dizesini alın ve denetlediğiniz DB ile eşleşip eşleşmediğine bakın:
Sorgunuzu çalıştırmadan önce aşağıdakileri ekleyin:
// EF6
var connectionString = db.Database.Connection.ConnectionString;
// EF Core 5
var connectionString = db.Database.GetConnectionString();
- Gerçekten sorguladığınız verilere bir göz atın:
.
var cars = db.CarRentalFields.Where(carNum =>
(carNum.CarNumber == carNumber1 && carNum.ActualReturnDate == null)).ToList();
Bu sorgu yalnızca 1 kaydı döndürebilirken, sorunun nedeni bu değildir. İstediğiniz şey, bu kayıt için CarNumber, StartDate, ReturnDate ve userıd'dir:
var car = db.CarRentalFields
.Where(carNum => carNum.CarNumber == carNumber1
&& carNum.ActualReturnDate == null)
.Select(x => new
{
x.CarNumber,
x.StartDay,
x.ReturnDate,
x.UserId
}).Single(); // Expect our 1 record here...
var cars = db.CarRentalFields
.Where(x => x.CarNumber == car.CarNumber
&& x.StartDay == car.StartDay
&& x.ReturnDate == car.ReturnDate
&& x.UserId == car.UserId)
.ToList(); // Get rows that match our returned Key fields.
Bu sorgular, güncellemek istediğiniz araç kaydının varsayılan PK değerlerini seçer, ardından beklenen Anahtar alanlarla eşleşen kayıtlar için araçlarda arama yapar. Param, üst sorgu 1 kayıt döndürürken, alt sorgu iki satır döndürür, yani yalnızca 1 kayıt #null ActualReturnDate değerine sahipken, Anahtarınız bu tablonun içeriği için yeterince benzersiz değildir.